Implement compatibility support for WRITE_SDCARD permission.
Now old applications will automatically be granted it. Also renamed it from SDCARD_WRITE to WRITE_SDCARD to be consistent with our other permissions, and re-arranged how we do targetSdkVersion to actually be usuable for this kind of stuff. Note that right now this results in basically all apps being given the WRITE_SDCARD permission, because their targetSdkVersion is not set. I will be dealing with that in a future change.
This commit is contained in:
@@ -870,17 +870,6 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="SDCARD_WRITE"
|
||||
type="java.lang.String"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value=""android.permission.SDCARD_WRITE""
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="SEND_SMS"
|
||||
type="java.lang.String"
|
||||
transient="false"
|
||||
@@ -1167,6 +1156,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="WRITE_SDCARD"
|
||||
type="java.lang.String"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value=""android.permission.WRITE_SDCARD""
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="WRITE_SECURE_SETTINGS"
|
||||
type="java.lang.String"
|
||||
transient="false"
|
||||
@@ -31824,6 +31824,16 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="targetSdkVersion"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="taskAffinity"
|
||||
type="java.lang.String"
|
||||
transient="false"
|
||||
@@ -31999,22 +32009,11 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_TARGETS_SDK"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="256"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_TEST_ONLY"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="512"
|
||||
value="256"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
@@ -86002,6 +86001,28 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="CUR_DEVELOPMENT"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="10000"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="DONUT"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="10000"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<class name="Bundle"
|
||||
extends="java.lang.Object"
|
||||
@@ -139611,6 +139632,17 @@
|
||||
<implements name="java.lang.annotation.Annotation">
|
||||
</implements>
|
||||
</class>
|
||||
<class name="ViewDebug.FlagToString"
|
||||
extends="java.lang.Object"
|
||||
abstract="true"
|
||||
static="true"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<implements name="java.lang.annotation.Annotation">
|
||||
</implements>
|
||||
</class>
|
||||
<class name="ViewDebug.HierarchyTraceType"
|
||||
extends="java.lang.Enum"
|
||||
abstract="false"
|
||||
|
||||
@@ -123,13 +123,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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_TEST_ONLY = 1<<9;
|
||||
public static final int FLAG_TEST_ONLY = 1<<8;
|
||||
|
||||
/**
|
||||
* Flags associated with the application. Any combination of
|
||||
@@ -137,7 +131,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
|
||||
* {@link #FLAG_ALLOW_TASK_REPARENTING}
|
||||
* {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
|
||||
* {@link #FLAG_TARGETS_SDK}.
|
||||
* {@link #FLAG_TEST_ONLY}.
|
||||
*/
|
||||
public int flags = 0;
|
||||
|
||||
@@ -181,6 +175,16 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
*/
|
||||
public int[] supportsDensities;
|
||||
|
||||
/**
|
||||
* The minimum SDK version this application targets. It may run on earilier
|
||||
* versions, but it knows how to work with any new behavior added at this
|
||||
* version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
|
||||
* if this is a development build and the app is targeting that. You should
|
||||
* compare that this number is >= the SDK version number at which your
|
||||
* behavior was introduced.
|
||||
*/
|
||||
public int targetSdkVersion;
|
||||
|
||||
/**
|
||||
* When false, indicates that all components within this application are
|
||||
* considered disabled, regardless of their individually set enabled status.
|
||||
@@ -200,6 +204,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
pw.println(prefix + "publicSourceDir=" + publicSourceDir);
|
||||
pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
|
||||
pw.println(prefix + "dataDir=" + dataDir);
|
||||
pw.println(prefix + "targetSdkVersion=" + targetSdkVersion);
|
||||
pw.println(prefix + "enabled=" + enabled);
|
||||
pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
|
||||
pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
|
||||
@@ -246,6 +251,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
sharedLibraryFiles = orig.sharedLibraryFiles;
|
||||
dataDir = orig.dataDir;
|
||||
uid = orig.uid;
|
||||
targetSdkVersion = orig.targetSdkVersion;
|
||||
enabled = orig.enabled;
|
||||
manageSpaceActivityName = orig.manageSpaceActivityName;
|
||||
descriptionRes = orig.descriptionRes;
|
||||
@@ -276,6 +282,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
dest.writeStringArray(sharedLibraryFiles);
|
||||
dest.writeString(dataDir);
|
||||
dest.writeInt(uid);
|
||||
dest.writeInt(targetSdkVersion);
|
||||
dest.writeInt(enabled ? 1 : 0);
|
||||
dest.writeString(manageSpaceActivityName);
|
||||
dest.writeInt(descriptionRes);
|
||||
@@ -305,6 +312,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
sharedLibraryFiles = source.readStringArray();
|
||||
dataDir = source.readString();
|
||||
uid = source.readInt();
|
||||
targetSdkVersion = source.readInt();
|
||||
enabled = source.readInt() != 0;
|
||||
manageSpaceActivityName = source.readString();
|
||||
descriptionRes = source.readInt();
|
||||
|
||||
@@ -55,6 +55,30 @@ import java.util.jar.JarFile;
|
||||
* {@hide}
|
||||
*/
|
||||
public class PackageParser {
|
||||
/** @hide */
|
||||
public static class NewPermissionInfo {
|
||||
public final String name;
|
||||
public final int sdkVersion;
|
||||
public final int fileVersion;
|
||||
|
||||
public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
|
||||
this.name = name;
|
||||
this.sdkVersion = sdkVersion;
|
||||
this.fileVersion = fileVersion;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of new permissions that have been added since 1.0.
|
||||
* NOTE: These must be declared in SDK version order, with permissions
|
||||
* added to older SDKs appearing before those added to newer SDKs.
|
||||
* @hide
|
||||
*/
|
||||
public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = new PackageParser.NewPermissionInfo[] {
|
||||
new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_SDCARD,
|
||||
android.os.Build.VERSION_CODES.DONUT,
|
||||
0)
|
||||
};
|
||||
|
||||
private String mArchiveSourcePath;
|
||||
private String[] mSeparateProcesses;
|
||||
@@ -616,7 +640,6 @@ public class PackageParser {
|
||||
|
||||
final Package pkg = new Package(pkgName);
|
||||
boolean foundApp = false;
|
||||
boolean targetsSdk = false;
|
||||
|
||||
TypedArray sa = res.obtainAttributes(attrs,
|
||||
com.android.internal.R.styleable.AndroidManifest);
|
||||
@@ -774,11 +797,10 @@ public class PackageParser {
|
||||
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;
|
||||
pkg.applicationInfo.targetSdkVersion
|
||||
= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
} else {
|
||||
pkg.applicationInfo.targetSdkVersion = targetVers;
|
||||
}
|
||||
|
||||
if (minVers > mSdkVersion) {
|
||||
@@ -824,8 +846,18 @@ public class PackageParser {
|
||||
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
|
||||
}
|
||||
|
||||
if (targetsSdk) {
|
||||
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_TARGETS_SDK;
|
||||
final int NP = PackageParser.NEW_PERMISSIONS.length;
|
||||
for (int ip=0; ip<NP; ip++) {
|
||||
final PackageParser.NewPermissionInfo npi
|
||||
= PackageParser.NEW_PERMISSIONS[ip];
|
||||
if (pkg.applicationInfo.targetSdkVersion >= 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) {
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>Applications targeting this or a later release will get these
|
||||
* new changes in behavior:</p>
|
||||
* <ul>
|
||||
* <li> 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.)
|
||||
* </ul>
|
||||
*/
|
||||
public static final int DONUT = CUR_DEVELOPMENT;
|
||||
}
|
||||
|
||||
/** The type of build, like "user" or "eng". */
|
||||
|
||||
@@ -389,11 +389,11 @@
|
||||
android:description="@string/permgroupdesc_storage" />
|
||||
|
||||
<!-- Allows an application to write to the SD card -->
|
||||
<permission android:name="android.permission.SDCARD_WRITE"
|
||||
<permission android:name="android.permission.WRITE_SDCARD"
|
||||
android:permissionGroup="android.permission-group.STORAGE"
|
||||
android:label="@string/permlab_sdcardWrite"
|
||||
android:description="@string/permdesc_sdcardWrite"
|
||||
android:protectionLevel="normal" />
|
||||
android:protectionLevel="dangerous" />
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Permissions for low-level system interaction -->
|
||||
|
||||
@@ -1069,7 +1069,7 @@
|
||||
user dictionary.</string>
|
||||
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_sdcardWrite">write to SD card</string>
|
||||
<string name="permlab_sdcardWrite">modify/delete SD card contents</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string>
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<group gid="log" />
|
||||
</permission>
|
||||
|
||||
<permission name="android.permission.SDCARD_WRITE" >
|
||||
<permission name="android.permission.WRITE_SDCARD" >
|
||||
<group gid="sdcard_rw" />
|
||||
</permission>
|
||||
|
||||
@@ -84,6 +84,24 @@
|
||||
others should have a fairly open environment in which to
|
||||
interact with the system. -->
|
||||
|
||||
<!-- Standard permissions granted to the shell. -->
|
||||
<assign-permission name="android.permission.WRITE_SDCARD" uid="shell" />
|
||||
<assign-permission name="android.permission.SEND_SMS" uid="shell" />
|
||||
<assign-permission name="android.permission.CALL_PHONE" uid="shell" />
|
||||
<assign-permission name="android.permission.READ_CONTACTS" uid="shell" />
|
||||
<assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" />
|
||||
<assign-permission name="android.permission.READ_OWNER_DATA" uid="shell" />
|
||||
<assign-permission name="android.permission.WRITE_OWNER_DATA" uid="shell" />
|
||||
<assign-permission name="android.permission.READ_CALENDAR" uid="shell" />
|
||||
<assign-permission name="android.permission.WRITE_CALENDAR" uid="shell" />
|
||||
<assign-permission name="android.permission.READ_USER_DICTIONARY" uid="shell" />
|
||||
<assign-permission name="android.permission.WRITE_USER_DICTIONARY" uid="shell" />
|
||||
<assign-permission name="android.permission.ACCESS_FINE_LOCATION" uid="shell" />
|
||||
<assign-permission name="android.permission.ACCESS_COARSE_LOCATION" uid="shell" />
|
||||
<assign-permission name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" uid="shell" />
|
||||
<assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" />
|
||||
<assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" />
|
||||
<assign-permission name="android.permission.BLUETOOTH" uid="shell" />
|
||||
<!-- System tool permissions granted to the shell. -->
|
||||
<assign-permission name="android.permission.GET_TASKS" uid="shell" />
|
||||
<assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" />
|
||||
@@ -114,6 +132,8 @@
|
||||
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="shell" />
|
||||
<assign-permission name="android.permission.READ_FRAME_BUFFER" uid="shell" />
|
||||
<assign-permission name="android.permission.DEVICE_POWER" uid="shell" />
|
||||
<assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />
|
||||
<assign-permission name="android.permission.INSTALL_LOCATION_COLLECTOR" uid="shell" />
|
||||
|
||||
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
|
||||
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
|
||||
|
||||
@@ -2828,6 +2828,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<NP; ip++) {
|
||||
final PackageParser.NewPermissionInfo npi
|
||||
= PackageParser.NEW_PERMISSIONS[ip];
|
||||
if (npi.name.equals(perm)
|
||||
&& pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
|
||||
allowed = true;
|
||||
Log.i(TAG, "Auto-granting WRITE_SDCARD to old pkg "
|
||||
+ pkg.packageName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allowed) {
|
||||
@@ -3586,7 +3601,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
} else {
|
||||
// Re installation failed. Restore old information
|
||||
// Remove new pkg information
|
||||
removePackageLI(newPackage, true);
|
||||
if (newPackage != null) {
|
||||
removePackageLI(newPackage, true);
|
||||
}
|
||||
// Add back the old system package
|
||||
scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
|
||||
oldPkgSetting.resourcePath,
|
||||
|
||||
@@ -99,6 +99,17 @@ public:
|
||||
const android::Vector<const char*>& 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<const char*> mNoCompressExtensions;
|
||||
android::Vector<const char*> mResourceSourceDirs;
|
||||
|
||||
const char* mMinSdkVersion;
|
||||
const char* mTargetSdkVersion;
|
||||
const char* mMaxSdkVersion;
|
||||
const char* mVersionCode;
|
||||
const char* mVersionName;
|
||||
|
||||
/* file specification */
|
||||
int mArgc;
|
||||
char* const* mArgv;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -495,6 +495,58 @@ static void applyFileOverlay(const sp<AaptAssets>& assets,
|
||||
return;
|
||||
}
|
||||
|
||||
void addTagAttribute(const sp<XMLNode>& 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<XMLNode> root)
|
||||
{
|
||||
root = root->searchElement(String16(), String16("manifest"));
|
||||
if (root == NULL) {
|
||||
fprintf(stderr, "No <manifest> 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<XMLNode> 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)); \
|
||||
@@ -1013,7 +1065,15 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
|
||||
|
||||
// Generate final compiled manifest file.
|
||||
manifestFile->clearData();
|
||||
err = compileXmlFile(assets, manifestFile, &table);
|
||||
sp<XMLNode> 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;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,16 @@ status_t compileXmlFile(const sp<AaptAssets>& assets,
|
||||
if (root == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return compileXmlFile(assets, root, target, table, options);
|
||||
}
|
||||
|
||||
status_t compileXmlFile(const sp<AaptAssets>& assets,
|
||||
const sp<XMLNode>& root,
|
||||
const sp<AaptFile>& 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<AaptAssets
|
||||
} else if (id != 0) {
|
||||
if (id == 127) {
|
||||
if (mHaveAppPackage) {
|
||||
fprintf(stderr, "Included resource have two application packages!\n");
|
||||
fprintf(stderr, "Included resources have two application packages!\n");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
mHaveAppPackage = true;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
class XMLNode;
|
||||
class ResourceTable;
|
||||
|
||||
enum {
|
||||
@@ -34,6 +35,12 @@ status_t compileXmlFile(const sp<AaptAssets>& assets,
|
||||
ResourceTable* table,
|
||||
int options = XML_COMPILE_STANDARD_RESOURCE);
|
||||
|
||||
status_t compileXmlFile(const sp<AaptAssets>& assets,
|
||||
const sp<XMLNode>& xmlTree,
|
||||
const sp<AaptFile>& target,
|
||||
ResourceTable* table,
|
||||
int options = XML_COMPILE_STANDARD_RESOURCE);
|
||||
|
||||
status_t compileResourceFile(Bundle* bundle,
|
||||
const sp<AaptAssets>& assets,
|
||||
const sp<AaptFile>& in,
|
||||
|
||||
@@ -524,12 +524,30 @@ const Vector<sp<XMLNode> >& XMLNode::getChildren() const
|
||||
return mChildren;
|
||||
}
|
||||
|
||||
const String8& XMLNode::getFilename() const
|
||||
{
|
||||
return mFilename;
|
||||
}
|
||||
|
||||
const Vector<XMLNode::attribute_entry>&
|
||||
XMLNode::getAttributes() const
|
||||
{
|
||||
return mAttributes;
|
||||
}
|
||||
|
||||
const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
|
||||
const String16& name) const
|
||||
{
|
||||
for (size_t i=0; i<mAttributes.size(); i++) {
|
||||
const attribute_entry& ae(mAttributes.itemAt(i));
|
||||
if (ae.ns == ns && ae.name == name) {
|
||||
return &ae;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const String16& XMLNode::getCData() const
|
||||
{
|
||||
return mChars;
|
||||
@@ -550,6 +568,38 @@ int32_t XMLNode::getEndLineNumber() const
|
||||
return mEndLineNumber;
|
||||
}
|
||||
|
||||
sp<XMLNode> 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<mChildren.size(); i++) {
|
||||
sp<XMLNode> found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName);
|
||||
if (found != NULL) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp<XMLNode> XMLNode::getChildElement(const String16& tagNamespace, const String16& tagName)
|
||||
{
|
||||
for (size_t i=0; i<mChildren.size(); i++) {
|
||||
sp<XMLNode> 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<XMLNode>& child)
|
||||
{
|
||||
if (getType() == TYPE_CDATA) {
|
||||
@@ -561,6 +611,17 @@ status_t XMLNode::addChild(const sp<XMLNode>& child)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t XMLNode::insertChildAt(const sp<XMLNode>& 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)
|
||||
{
|
||||
|
||||
@@ -68,6 +68,8 @@ public:
|
||||
const String16& getElementName() const;
|
||||
const Vector<sp<XMLNode> >& getChildren() const;
|
||||
|
||||
const String8& getFilename() const;
|
||||
|
||||
struct attribute_entry {
|
||||
attribute_entry() : index(~(uint32_t)0), nameResId(0)
|
||||
{
|
||||
@@ -91,6 +93,8 @@ public:
|
||||
|
||||
const Vector<attribute_entry>& 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<XMLNode> searchElement(const String16& tagNamespace, const String16& tagName);
|
||||
|
||||
sp<XMLNode> getChildElement(const String16& tagNamespace, const String16& tagName);
|
||||
|
||||
status_t addChild(const sp<XMLNode>& child);
|
||||
|
||||
status_t insertChildAt(const sp<XMLNode>& child, size_t index);
|
||||
|
||||
status_t addAttribute(const String16& ns, const String16& name,
|
||||
const String16& value);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user