Merge "Implement system data migration support."

This commit is contained in:
Dianne Hackborn
2010-02-03 18:18:56 -08:00
committed by Android (Google) Code Review
7 changed files with 556 additions and 49 deletions

View File

@@ -78,6 +78,30 @@ int uninstall(const char *pkgname, int encrypted_fs_flag)
return delete_dir_contents(pkgdir, 1, 0);
}
int renamepkg(const char *oldpkgname, const char *newpkgname, int encrypted_fs_flag)
{
char oldpkgdir[PKG_PATH_MAX];
char newpkgdir[PKG_PATH_MAX];
if (encrypted_fs_flag == USE_UNENCRYPTED_FS) {
if (create_pkg_path(oldpkgdir, PKG_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX))
return -1;
if (create_pkg_path(newpkgdir, PKG_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX))
return -1;
} else {
if (create_pkg_path(oldpkgdir, PKG_SEC_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX))
return -1;
if (create_pkg_path(newpkgdir, PKG_SEC_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX))
return -1;
}
if (rename(oldpkgdir, newpkgdir) < 0) {
LOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
return -errno;
}
return 0;
}
int delete_user_data(const char *pkgname, int encrypted_fs_flag)
{
char pkgdir[PKG_PATH_MAX];
@@ -636,3 +660,203 @@ fail:
}
return -1;
}
int create_move_path(char path[PKG_PATH_MAX],
const char* prefix,
const char* pkgname,
const char* leaf)
{
if ((strlen(prefix) + strlen(pkgname) + strlen(leaf) + 1) >= PKG_PATH_MAX) {
return -1;
}
sprintf(path, "%s%s/%s", prefix, pkgname, leaf);
return 0;
}
void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid)
{
while (path[basepos] != 0) {
if (path[basepos] == '/') {
path[basepos] = 0;
LOGI("Making directory: %s\n", path);
if (mkdir(path, mode) == 0) {
chown(path, uid, gid);
}
path[basepos] = '/';
basepos++;
}
basepos++;
}
}
int movefiles()
{
DIR *d;
int dfd, subfd;
struct dirent *de;
struct stat s;
char buf[PKG_PATH_MAX+1];
int bufp, bufe, bufi, readlen;
char srcpkg[PKG_NAME_MAX];
char dstpkg[PKG_NAME_MAX];
char srcpath[PKG_PATH_MAX];
char dstpath[PKG_PATH_MAX];
int dstuid, dstgid;
int hasspace;
d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
if (d == NULL) {
goto done;
}
dfd = dirfd(d);
/* Iterate through all files in the directory, executing the
* file movements requested there-in.
*/
while ((de = readdir(d))) {
const char *name = de->d_name;
if (de->d_type == DT_DIR) {
continue;
} else {
subfd = openat(dfd, name, O_RDONLY);
if (subfd < 0) {
LOGW("Unable to open update commands at %s%s\n",
UPDATE_COMMANDS_DIR_PREFIX, name);
continue;
}
bufp = 0;
bufe = 0;
buf[PKG_PATH_MAX] = 0;
srcpkg[0] = dstpkg[0] = 0;
while (1) {
bufi = bufp;
while (bufi < bufe && buf[bufi] != '\n') {
bufi++;
}
if (bufi < bufe) {
buf[bufi] = 0;
LOGV("Processing line: %s\n", buf+bufp);
hasspace = 0;
while (bufp < bufi && isspace(buf[bufp])) {
hasspace = 1;
bufp++;
}
if (buf[bufp] == '#' || bufp == bufi) {
// skip comments and empty lines.
} else if (hasspace) {
if (dstpkg[0] == 0) {
LOGW("Path before package line in %s%s: %s\n",
UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
} else if (srcpkg[0] == 0) {
// Skip -- source package no longer exists.
} else {
LOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
if (!create_move_path(srcpath, PKG_DIR_PREFIX, srcpkg, buf+bufp) &&
!create_move_path(dstpath, PKG_DIR_PREFIX, dstpkg, buf+bufp)) {
LOGI("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
mkinnerdirs(dstpath, strlen(dstpath)-(bufi-bufp),
S_IRWXU|S_IRWXG|S_IXOTH, dstuid, dstgid);
if (rename(srcpath, dstpath) >= 0) {
if (chown(dstpath, dstuid, dstgid) < 0) {
LOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
unlink(dstpath);
}
} else {
LOGW("Unable to rename %s to %s: %s\n",
srcpath, dstpath, strerror(errno));
}
}
}
} else {
char* div = strchr(buf+bufp, ':');
if (div == NULL) {
LOGW("Bad package spec in %s%s; no ':' sep: %s\n",
UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
} else {
*div = 0;
div++;
if (strlen(buf+bufp) < PKG_NAME_MAX) {
strcpy(dstpkg, buf+bufp);
} else {
srcpkg[0] = dstpkg[0] = 0;
LOGW("Package name too long in %s%s: %s\n",
UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
}
if (strlen(div) < PKG_NAME_MAX) {
strcpy(srcpkg, div);
} else {
srcpkg[0] = dstpkg[0] = 0;
LOGW("Package name too long in %s%s: %s\n",
UPDATE_COMMANDS_DIR_PREFIX, name, div);
}
if (srcpkg[0] != 0) {
if (!create_pkg_path(srcpath, PKG_DIR_PREFIX, srcpkg,
PKG_DIR_POSTFIX)) {
if (lstat(srcpath, &s) < 0) {
// Package no longer exists -- skip.
srcpkg[0] = 0;
}
} else {
srcpkg[0] = 0;
LOGW("Can't create path %s in %s%s\n",
div, UPDATE_COMMANDS_DIR_PREFIX, name);
}
if (srcpkg[0] != 0) {
if (!create_pkg_path(dstpath, PKG_DIR_PREFIX, dstpkg,
PKG_DIR_POSTFIX)) {
if (lstat(dstpath, &s) == 0) {
dstuid = s.st_uid;
dstgid = s.st_gid;
} else {
srcpkg[0] = 0;
LOGW("Can't stat path %s in %s%s: %s\n",
dstpath, UPDATE_COMMANDS_DIR_PREFIX,
name, strerror(errno));
}
} else {
srcpkg[0] = 0;
LOGW("Can't create path %s in %s%s\n",
div, UPDATE_COMMANDS_DIR_PREFIX, name);
}
}
LOGV("Transfering from %s to %s: uid=%d\n",
srcpkg, dstpkg, dstuid);
}
}
}
bufp = bufi+1;
} else {
if (bufp == 0) {
if (bufp < bufe) {
LOGW("Line too long in %s%s, skipping: %s\n",
UPDATE_COMMANDS_DIR_PREFIX, name, buf);
}
} else if (bufp < bufe) {
memcpy(buf, buf+bufp, bufe-bufp);
bufe -= bufp;
bufp = 0;
}
readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
if (readlen < 0) {
LOGW("Failure reading update commands in %s%s: %s\n",
UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
break;
} else if (readlen == 0) {
break;
}
bufe += readlen;
buf[bufe] = 0;
LOGV("Read buf: %s\n", buf);
}
}
close(subfd);
}
}
closedir(d);
done:
return 0;
}

View File

@@ -53,6 +53,11 @@ static int do_remove(char **arg, char reply[REPLY_MAX])
return uninstall(arg[0], atoi(arg[1])); /* pkgname */
}
static int do_rename(char **arg, char reply[REPLY_MAX])
{
return renamepkg(arg[0], arg[1], atoi(arg[2])); /* oldpkgname, newpkgname */
}
static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
{
return free_cache(atoi(arg[0])); /* free_size */
@@ -87,6 +92,11 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
return delete_user_data(arg[0], atoi(arg[1])); /* pkgname */
}
static int do_movefiles(char **arg, char reply[REPLY_MAX])
{
return movefiles();
}
struct cmdinfo {
const char *name;
unsigned numargs;
@@ -100,11 +110,13 @@ struct cmdinfo cmds[] = {
{ "movedex", 2, do_move_dex },
{ "rmdex", 1, do_rm_dex },
{ "remove", 2, do_remove },
{ "rename", 3, do_rename },
{ "freecache", 1, do_free_cache },
{ "rmcache", 2, do_rm_cache },
{ "protect", 2, do_protect },
{ "getsize", 4, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
};
static int readx(int s, void *_buf, int count)

View File

@@ -73,6 +73,7 @@
#define DALVIK_CACHE_PREFIX "/data/dalvik-cache/"
#define DALVIK_CACHE_POSTFIX "/classes.dex"
#define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/"
#define PKG_NAME_MAX 128 /* largest allowed package name */
#define PKG_PATH_MAX 256 /* max size of any path we use */
@@ -97,6 +98,7 @@ int delete_dir_contents_fd(int dfd, const char *name);
int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid);
int uninstall(const char *pkgname, int encrypted_fs_flag);
int renamepkg(const char *oldpkgname, const char *newpkgname, int encrypted_fs_flag);
int delete_user_data(const char *pkgname, int encrypted_fs_flag);
int delete_cache(const char *pkgname, int encrypted_fs_flag);
int move_dex(const char *src, const char *dst);
@@ -106,3 +108,4 @@ int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpa
int *codesize, int *datasize, int *cachesize, int encrypted_fs_flag);
int free_cache(int free_size);
int dexopt(const char *apk_path, uid_t uid, int is_public);
int movefiles();

View File

@@ -953,6 +953,39 @@ public class PackageParser {
return null;
}
} else if (tagName.equals("original-package")) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestOriginalPackage);
String name = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestOriginalPackage_name);
sa.recycle();
if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
pkg.mOriginalPackage = name;
}
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("adopt-permissions")) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestOriginalPackage);
String name = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestOriginalPackage_name);
sa.recycle();
if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
if (pkg.mAdoptPermissions == null) {
pkg.mAdoptPermissions = new ArrayList<String>();
}
pkg.mAdoptPermissions.add(name);
}
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("eat-comment")) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
@@ -2528,6 +2561,9 @@ public class PackageParser {
public ArrayList<String> usesOptionalLibraries = null;
public String[] usesLibraryFiles = null;
public String mOriginalPackage = null;
public ArrayList<String> mAdoptPermissions = null;
// We store the application meta-data independently to avoid multiple unwanted references
public Bundle mAppMetaData = null;

View File

@@ -923,6 +923,19 @@
<attr name="name" />
</declare-styleable>
<!-- Private tag to declare the original package name that this package is
based on. Only used for packages installed in the system image. If
given, and different than the actual package name, and the given
original package was previously installed on the device but the new
one was not, then the data for the old one will be renamed to be
for the new package.
<p>This appears as a child tag of the root
{@link #AndroidManifest manifest} tag. -->
<declare-styleable name="AndroidManifestOriginalPackage" parent="AndroidManifest">
<attr name="name" />
</declare-styleable>
<!-- The <code>provider</code> tag declares a
{@link android.content.ContentProvider} class that is available
as part of the package's application components, supplying structured

View File

@@ -222,6 +222,21 @@ class Installer {
return execute(builder.toString());
}
public int rename(String oldname, String newname, boolean useEncryptedFilesystem) {
StringBuilder builder = new StringBuilder("rename");
builder.append(' ');
builder.append(oldname);
builder.append(' ');
builder.append(newname);
builder.append(' ');
if (useEncryptedFilesystem) {
builder.append('1');
} else {
builder.append('0');
}
return execute(builder.toString());
}
public int deleteCacheFiles(String name, boolean useEncryptedFilesystem) {
StringBuilder builder = new StringBuilder("rmcache");
builder.append(' ');
@@ -308,4 +323,8 @@ class Installer {
return -1;
}
}
public int moveFiles() {
return execute("movefiles");
}
}

View File

@@ -96,11 +96,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@@ -117,6 +119,7 @@ class PackageManagerService extends IPackageManager.Stub {
private static final String TAG = "PackageManager";
private static final boolean DEBUG_SETTINGS = false;
private static final boolean DEBUG_PREFERRED = false;
private static final boolean DEBUG_UPGRADE = false;
private static final boolean MULTIPLE_APPLICATION_UIDS = true;
private static final int RADIO_UID = Process.PHONE_UID;
@@ -221,7 +224,6 @@ class PackageManagerService extends IPackageManager.Stub {
final Settings mSettings;
boolean mRestoredSettings;
boolean mReportedUidError;
// Group-ids that are given to all packages as read from etc/permissions/*.xml.
int[] mGlobalGids;
@@ -271,6 +273,10 @@ class PackageManagerService extends IPackageManager.Stub {
final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
new HashMap<String, PackageParser.PermissionGroup>();
// Packages whose data we have transfered into another package, thus
// should no longer exist.
final HashSet<String> mTransferedPackages = new HashSet<String>();
// Broadcast actions that are only available to the system.
final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
@@ -661,16 +667,43 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
// Find base frameworks (resource packages without code).
mFrameworkInstallObserver = new AppDirObserver(
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
scanMode | SCAN_NO_DEX);
// Collect all system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
if (mInstaller != null) {
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles();
}
// Prune any system packages that no longer exist.
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
&& !mPackages.containsKey(ps.name)) {
psit.remove();
String msg = "System package " + ps.name
+ " no longer exists; wiping its data";
reportSettingsProblem(Log.WARN, msg);
if (mInstaller != null) {
// XXX how to set useEncryptedFSDir for packages that
// are not encrypted?
mInstaller.remove(ps.name, true);
}
}
}
mAppInstallDir = new File(dataDir, "app");
if (mInstaller == null) {
// Make sure these dirs exist, when we are running in
@@ -2081,14 +2114,21 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
private static File getSettingsProblemFile() {
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
File fname = new File(systemDir, "uiderrors.txt");
return fname;
}
private static void reportSettingsProblem(int priority, String msg) {
try {
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
File fname = new File(systemDir, "uiderrors.txt");
File fname = getSettingsProblemFile();
FileOutputStream out = new FileOutputStream(fname, true);
PrintWriter pw = new PrintWriter(out);
pw.println(msg);
SimpleDateFormat formatter = new SimpleDateFormat();
String dateString = formatter.format(new Date(System.currentTimeMillis()));
pw.println(dateString + ": " + msg);
pw.close();
FileUtils.setPermissions(
fname.toString(),
@@ -2295,6 +2335,21 @@ class PackageManagerService extends IPackageManager.Stub {
((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
}
private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Log.w(TAG, "Unable to update from " + oldPkg.name
+ " to " + newPkg.packageName
+ ": old package not in system partition");
return false;
} else if (mPackages.get(oldPkg.name) != null) {
Log.w(TAG, "Unable to update from " + oldPkg.name
+ " to " + newPkg.packageName
+ ": old package still exists");
return false;
}
return true;
}
private PackageParser.Package scanPackageLI(
PackageParser.Package pkg, int parseFlags, int scanMode) {
File scanFile = new File(pkg.mScanPath);
@@ -2439,22 +2494,67 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
// Check if we are renaming from an original package name.
PackageSetting origPackage = null;
if (pkg.mOriginalPackage != null) {
// We will only retrieve the setting for it if it already
// exists; otherwise we need to make a new one later.
origPackage = mSettings.peekPackageLP(pkg.mOriginalPackage);
if (origPackage != null) {
if (!verifyPackageUpdate(origPackage, pkg)) {
origPackage = null;
} else if (origPackage.sharedUser != null) {
if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Log.w(TAG, "Unable to migrate data from " + origPackage.name
+ " to " + pkg.packageName + ": old uid "
+ origPackage.sharedUser.name
+ " differs from " + pkg.mSharedUserId);
origPackage = null;
}
} else {
if (DEBUG_UPGRADE) Log.v(TAG, "Migrating data from "
+ origPackage.name + " to " + pkg.packageName);
}
}
}
if (mTransferedPackages.contains(pkg.packageName)) {
Log.w(TAG, "Package " + pkg.packageName
+ " was transferred to another, but its .apk remains");
}
// Just create the setting, don't add it yet. For already existing packages
// the PkgSetting exists already and doesn't have to be created.
pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
pkgSetting = mSettings.getPackageLP(pkg, origPackage, suid, destCodeFile,
destResourceFile, pkg.applicationInfo.flags, true, false);
if (pkgSetting == null) {
Log.w(TAG, "Creating application package " + pkgName + " failed");
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
pkg.applicationInfo.uid = pkgSetting.userId;
pkg.mExtras = pkgSetting;
if (pkg.mAdoptPermissions != null) {
// This package wants to adopt ownership of permissions from
// another package.
for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
String origName = pkg.mAdoptPermissions.get(i);
PackageSetting orig = mSettings.peekPackageLP(origName);
if (orig != null) {
if (verifyPackageUpdate(orig, pkg)) {
if (DEBUG_UPGRADE) Log.v(TAG, "Adopting permissions from "
+ origName + " to " + pkg.packageName);
mSettings.transferPermissions(origName, pkg.packageName);
}
}
}
}
if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
(scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
@@ -2543,6 +2643,9 @@ class PackageManagerService extends IPackageManager.Stub {
} else {
dataPath = new File(mAppDataDir, pkgName);
}
boolean uidError = false;
if (dataPath.exists()) {
mOutPermissions[1] = 0;
FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
@@ -2556,7 +2659,7 @@ class PackageManagerService extends IPackageManager.Stub {
// current data so the application will still work.
if (mInstaller != null) {
int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
if(ret >= 0) {
if (ret >= 0) {
// Old data gone!
String msg = "System package " + pkg.packageName
+ " has changed from uid: "
@@ -2591,12 +2694,12 @@ class PackageManagerService extends IPackageManager.Stub {
+ mOutPermissions[1] + " on disk, "
+ pkg.applicationInfo.uid + " in settings";
synchronized (mPackages) {
if (!mReportedUidError) {
mReportedUidError = true;
msg = msg + "; read messages:\n"
+ mSettings.getReadMessagesLP();
mSettings.mReadMessages.append(msg);
mSettings.mReadMessages.append('\n');
uidError = true;
if (!pkgSetting.uidError) {
reportSettingsProblem(Log.ERROR, msg);
}
reportSettingsProblem(Log.ERROR, msg);
}
}
}
@@ -2604,6 +2707,29 @@ class PackageManagerService extends IPackageManager.Stub {
} else {
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
Log.v(TAG, "Want this data dir: " + dataPath);
if (pkgSetting.origPackage != null) {
synchronized (mPackages) {
// This package is being update from another; rename the
// old one's data dir.
String msg = "Transfering data from old package "
+ pkgSetting.origPackage.name + " to new package "
+ pkgSetting.name;
reportSettingsProblem(Log.WARN, msg);
if (mInstaller != null) {
int ret = mInstaller.rename(pkgSetting.origPackage.name,
pkgName, useEncryptedFSDir);
if(ret < 0) {
msg = "Error transfering data from old package "
+ pkgSetting.origPackage.name + " to new package "
+ pkgSetting.name;
reportSettingsProblem(Log.WARN, msg);
}
}
// And now uninstall the old package.
mInstaller.remove(pkgSetting.origPackage.name, useEncryptedFSDir);
mSettings.removePackageLP(pkgSetting.origPackage.name);
}
}
//invoke installer to do the actual installation
if (mInstaller != null) {
int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
@@ -2629,8 +2755,16 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.dataDir = null;
}
}
pkgSetting.uidError = uidError;
}
// No longer need to retain this.
if (pkgSetting.origPackage != null) {
mTransferedPackages.add(pkgSetting.origPackage.name);
pkgSetting.origPackage = null;
}
// Perform shared library installation and dex validation and
// optimization, if this is not a system app.
if (mInstaller != null) {
@@ -5951,16 +6085,31 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
}
pw.println(" ");
pw.println("Settings parse messages:");
pw.println(mSettings.mReadMessages.toString());
pw.println(" ");
pw.println("Package warning messages:");
File fname = getSettingsProblemFile();
FileInputStream in;
try {
in = new FileInputStream(fname);
int avail = in.available();
byte[] data = new byte[avail];
in.read(data);
pw.println(new String(data));
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
synchronized (mProviders) {
pw.println(" ");
pw.println("Registered ContentProviders:");
for (PackageParser.Provider p : mProviders.values()) {
pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
pw.println(p.toString());
}
}
@@ -5972,7 +6121,7 @@ class PackageManagerService extends IPackageManager.Stub {
final static int TYPE_DYNAMIC = 2;
final String name;
final String sourcePackage;
String sourcePackage;
final int type;
PackageParser.Permission perm;
PermissionInfo pendingInfo;
@@ -6437,6 +6586,8 @@ class PackageManagerService extends IPackageManager.Stub {
private String timeStampString = "0";
int versionCode;
boolean uidError;
PackageSignatures signatures = new PackageSignatures();
boolean permissionsFixed;
@@ -6448,6 +6599,8 @@ class PackageManagerService extends IPackageManager.Stub {
int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
int installStatus = PKG_INSTALL_COMPLETE;
PackageSettingBase origPackage;
/* package name of the app that installed this package */
String installerPackageName;
@@ -6455,13 +6608,17 @@ class PackageManagerService extends IPackageManager.Stub {
int pVersionCode, int pkgFlags) {
super(pkgFlags);
this.name = name;
init(codePath, resourcePath, pVersionCode);
}
void init(File codePath, File resourcePath, int pVersionCode) {
this.codePath = codePath;
this.codePathString = codePath.toString();
this.resourcePath = resourcePath;
this.resourcePathString = resourcePath.toString();
this.versionCode = pVersionCode;
}
public void setInstallerPackageName(String packageName) {
installerPackageName = packageName;
}
@@ -6667,11 +6824,11 @@ class PackageManagerService extends IPackageManager.Stub {
mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
}
PackageSetting getPackageLP(PackageParser.Package pkg,
PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
SharedUserSetting sharedUser, File codePath, File resourcePath,
int pkgFlags, boolean create, boolean add) {
final String name = pkg.packageName;
PackageSetting p = getPackageLP(name, sharedUser, codePath,
PackageSetting p = getPackageLP(name, origPackage, sharedUser, codePath,
resourcePath, pkg.mVersionCode, pkgFlags, create, add);
return p;
}
@@ -6813,7 +6970,31 @@ class PackageManagerService extends IPackageManager.Stub {
return null;
}
private PackageSetting getPackageLP(String name,
// Transfer ownership of permissions from one package to another.
private void transferPermissions(String origPkg, String newPkg) {
// Transfer ownership of permissions to the new package.
for (int i=0; i<2; i++) {
HashMap<String, BasePermission> permissions =
i == 0 ? mPermissionTrees : mPermissions;
for (BasePermission bp : permissions.values()) {
if (origPkg.equals(bp.sourcePackage)) {
if (DEBUG_UPGRADE) Log.v(TAG,
"Moving permission " + bp.name
+ " from pkg " + bp.sourcePackage
+ " to " + newPkg);
bp.sourcePackage = newPkg;
bp.perm = null;
if (bp.pendingInfo != null) {
bp.sourcePackage = newPkg;
}
bp.uid = 0;
bp.gids = null;
}
}
}
}
private PackageSetting getPackageLP(String name, PackageSetting origPackage,
SharedUserSetting sharedUser, File codePath, File resourcePath,
int vc, int pkgFlags, boolean create, boolean add) {
PackageSetting p = mPackages.get(name);
@@ -6857,36 +7038,49 @@ class PackageManagerService extends IPackageManager.Stub {
return null;
}
p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
p.setTimeStamp(codePath.lastModified());
p.sharedUser = sharedUser;
if (sharedUser != null) {
p.userId = sharedUser.userId;
} else if (MULTIPLE_APPLICATION_UIDS) {
// Clone the setting here for disabled system packages
PackageSetting dis = mDisabledSysPackages.get(name);
if (dis != null) {
// For disabled packages a new setting is created
// from the existing user id. This still has to be
// added to list of user id's
// Copy signatures from previous setting
if (dis.signatures.mSignatures != null) {
p.signatures.mSignatures = dis.signatures.mSignatures.clone();
}
p.userId = dis.userId;
// Clone permissions
p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
// Clone component info
p.disabledComponents = new HashSet<String>(dis.disabledComponents);
p.enabledComponents = new HashSet<String>(dis.enabledComponents);
// Add new setting to list of user ids
addUserIdLP(p.userId, p, name);
} else {
// Assign new user id
p.userId = newUserIdLP(p);
}
if (origPackage != null) {
// We are consuming the data from an existing package.
if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
+ " is adopting original package " + origPackage.name);
p.copyFrom(origPackage);
p.sharedUser = origPackage.sharedUser;
p.userId = origPackage.userId;
p.origPackage = origPackage;
transferPermissions(origPackage.name, name);
// Update new package state.
p.setTimeStamp(codePath.lastModified());
} else {
p.userId = FIRST_APPLICATION_UID;
p.setTimeStamp(codePath.lastModified());
p.sharedUser = sharedUser;
if (sharedUser != null) {
p.userId = sharedUser.userId;
} else if (MULTIPLE_APPLICATION_UIDS) {
// Clone the setting here for disabled system packages
PackageSetting dis = mDisabledSysPackages.get(name);
if (dis != null) {
// For disabled packages a new setting is created
// from the existing user id. This still has to be
// added to list of user id's
// Copy signatures from previous setting
if (dis.signatures.mSignatures != null) {
p.signatures.mSignatures = dis.signatures.mSignatures.clone();
}
p.userId = dis.userId;
// Clone permissions
p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
// Clone component info
p.disabledComponents = new HashSet<String>(dis.disabledComponents);
p.enabledComponents = new HashSet<String>(dis.enabledComponents);
// Add new setting to list of user ids
addUserIdLP(p.userId, p, name);
} else {
// Assign new user id
p.userId = newUserIdLP(p);
}
} else {
p.userId = FIRST_APPLICATION_UID;
}
}
if (p.userId < 0) {
reportSettingsProblem(Log.WARN,
@@ -7248,6 +7442,9 @@ class PackageManagerService extends IPackageManager.Stub {
serializer.attribute(null, "sharedUserId",
Integer.toString(pkg.userId));
}
if (pkg.uidError) {
serializer.attribute(null, "uidError", "true");
}
if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
serializer.attribute(null, "enabled",
pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
@@ -7441,7 +7638,7 @@ class PackageManagerService extends IPackageManager.Stub {
final PendingPackage pp = mPendingPackages.get(i);
Object idObj = getUserIdLP(pp.sharedId);
if (idObj != null && idObj instanceof SharedUserSetting) {
PackageSetting p = getPackageLP(pp.name,
PackageSetting p = getPackageLP(pp.name, null,
(SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
pp.versionCode, pp.pkgFlags, true, true);
if (p == null) {
@@ -7610,6 +7807,7 @@ class PackageManagerService extends IPackageManager.Stub {
String resourcePathStr = null;
String systemStr = null;
String installerPackageName = null;
String uidError = null;
int pkgFlags = 0;
String timeStampStr;
long timeStamp = 0;
@@ -7619,6 +7817,7 @@ class PackageManagerService extends IPackageManager.Stub {
try {
name = parser.getAttributeValue(null, "name");
idStr = parser.getAttributeValue(null, "userId");
uidError = parser.getAttributeValue(null, "uidError");
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
codePathStr = parser.getAttributeValue(null, "codePath");
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
@@ -7712,6 +7911,7 @@ class PackageManagerService extends IPackageManager.Stub {
+ parser.getPositionDescription());
}
if (packageSetting != null) {
packageSetting.uidError = "true".equals(uidError);
packageSetting.installerPackageName = installerPackageName;
final String enabledStr = parser.getAttributeValue(null, "enabled");
if (enabledStr != null) {