app install on sdcard. provide skeleton implementation
to install an app on sdcard, just resources. Add new install path for /asec in installd. ignore . when checking for apk path since the sdcard packages id'ed by package name. Add new -s option to adb shell pm Refactor fwd locked from scanMode to ApplicationInfo. Add new flag for sd install Add new parse flags for fwd locking and installing on sdcard New mock api's in PackageManagerService to invoke MountService api's. These will be refactored again and so have been wrapped internally. Some error codes in PackageManager Changes in PackageManagerService to use mPath and mScanPath during installation and switch to using PackageParser.Package.applicationInfo attributes for source and public resource directories. Some known issues that will be addressed later using system_uid for now. needs some tinkering with uid and packagesetting creation to use the actual app uid error handling from vold not very robust. ignoring lot of things for now sending a delayed destroy to delete packages. will revisit later revisit temp file creation later. just copy for now
This commit is contained in:
@@ -135,8 +135,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
static final int SCAN_NO_DEX = 1<<1;
|
||||
static final int SCAN_FORCE_DEX = 1<<2;
|
||||
static final int SCAN_UPDATE_SIGNATURE = 1<<3;
|
||||
static final int SCAN_FORWARD_LOCKED = 1<<4;
|
||||
static final int SCAN_NEW_INSTALL = 1<<5;
|
||||
static final int SCAN_NEW_INSTALL = 1<<4;
|
||||
static final int SCAN_NO_PATHS = 1<<5;
|
||||
|
||||
final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
|
||||
Process.THREAD_PRIORITY_BACKGROUND);
|
||||
@@ -281,8 +281,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
final HashMap<String, ArrayList<String>> mPendingBroadcasts
|
||||
= new HashMap<String, ArrayList<String>>();
|
||||
static final int SEND_PENDING_BROADCAST = 1;
|
||||
static final int DESTROY_SD_CONTAINER = 2;
|
||||
// Delay time in millisecs
|
||||
static final int BROADCAST_DELAY = 10 * 1000;
|
||||
static final int DESTROY_SD_CONTAINER_DELAY = 30 * 1000;
|
||||
|
||||
class PackageHandler extends Handler {
|
||||
PackageHandler(Looper looper) {
|
||||
@@ -290,6 +292,15 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case DESTROY_SD_CONTAINER:
|
||||
String pkgName = (String) msg.obj;
|
||||
if (pkgName != null) {
|
||||
// Too bad we cannot handle the errors from destroying the containers.
|
||||
if (!destroySdDir(pkgName)) {
|
||||
Log.e(TAG, "Failed to destroy container for pkg : " + pkgName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SEND_PENDING_BROADCAST : {
|
||||
String packages[];
|
||||
ArrayList components[];
|
||||
@@ -562,12 +573,12 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
|
||||
mFrameworkInstallObserver.startWatching();
|
||||
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
|
||||
scanMode | SCAN_NO_DEX);
|
||||
scanMode | SCAN_NO_DEX | SCAN_NO_PATHS);
|
||||
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
|
||||
mSystemInstallObserver = new AppDirObserver(
|
||||
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
|
||||
mSystemInstallObserver.startWatching();
|
||||
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
|
||||
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode | SCAN_NO_PATHS);
|
||||
mAppInstallDir = new File(dataDir, "app");
|
||||
if (mInstaller == null) {
|
||||
// Make sure these dirs exist, when we are running in
|
||||
@@ -594,7 +605,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
mDrmAppInstallObserver = new AppDirObserver(
|
||||
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
|
||||
mDrmAppInstallObserver.startWatching();
|
||||
scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
|
||||
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
|
||||
|
||||
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
|
||||
SystemClock.uptimeMillis());
|
||||
@@ -1961,12 +1972,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
int i;
|
||||
for (i=0; i<files.length; i++) {
|
||||
File file = new File(dir, files[i]);
|
||||
File resFile = file;
|
||||
// Pick up the resource path from settings for fwd locked apps
|
||||
if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
|
||||
resFile = null;
|
||||
}
|
||||
PackageParser.Package pkg = scanPackageLI(file, file, resFile,
|
||||
PackageParser.Package pkg = scanPackageLI(file,
|
||||
flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
|
||||
}
|
||||
}
|
||||
@@ -2009,14 +2015,15 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
* Returns null in case of errors and the error code is stored in mLastScanError
|
||||
*/
|
||||
private PackageParser.Package scanPackageLI(File scanFile,
|
||||
File destCodeFile, File destResourceFile, int parseFlags,
|
||||
int parseFlags,
|
||||
int scanMode) {
|
||||
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
|
||||
parseFlags |= mDefParseFlags;
|
||||
PackageParser pp = new PackageParser(scanFile.getPath());
|
||||
pp.setSeparateProcesses(mSeparateProcesses);
|
||||
final PackageParser.Package pkg = pp.parsePackage(scanFile,
|
||||
destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
|
||||
scanFile.getPath(),
|
||||
mMetrics, parseFlags);
|
||||
if (pkg == null) {
|
||||
mLastScanError = pp.getParseError();
|
||||
return null;
|
||||
@@ -2062,16 +2069,12 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
// The apk is forward locked (not public) if its code and resources
|
||||
// are kept in different files.
|
||||
// TODO grab this value from PackageSettings
|
||||
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
|
||||
scanMode |= SCAN_FORWARD_LOCKED;
|
||||
}
|
||||
File resFile = destResourceFile;
|
||||
if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
|
||||
resFile = getFwdLockedResource(ps.name);
|
||||
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
|
||||
}
|
||||
// Note that we invoke the following method only if we are about to unpack an application
|
||||
return scanPackageLI(scanFile, destCodeFile, resFile,
|
||||
pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
|
||||
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
|
||||
}
|
||||
|
||||
private static String fixProcessName(String defProcessName,
|
||||
@@ -2138,7 +2141,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
try {
|
||||
if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
|
||||
ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
|
||||
!pkg.mForwardLocked);
|
||||
!isForwardLocked(pkg));
|
||||
pkg.mDidDexOpt = true;
|
||||
performed = true;
|
||||
}
|
||||
@@ -2164,9 +2167,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
private PackageParser.Package scanPackageLI(
|
||||
File scanFile, File destCodeFile, File destResourceFile,
|
||||
PackageParser.Package pkg, int parseFlags, int scanMode) {
|
||||
|
||||
File scanFile = new File(pkg.mScanPath);
|
||||
mScanningPath = scanFile;
|
||||
if (pkg == null) {
|
||||
mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
|
||||
@@ -2223,6 +2225,43 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Initialize package source and resource directories
|
||||
File destResourceFile = null;
|
||||
File destCodeFile = null;
|
||||
if ((scanMode & SCAN_NO_PATHS) == 0) {
|
||||
boolean fwdLocked = (parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0;
|
||||
final String pkgFileName = pkgName + ".apk";
|
||||
File destDir = null;
|
||||
|
||||
if (fwdLocked) {
|
||||
destDir = mDrmAppPrivateInstallDir;
|
||||
destResourceFile = new File(mAppInstallDir, pkgName + ".zip");
|
||||
} else {
|
||||
boolean onSd = (parseFlags & PackageParser.PARSE_ON_SDCARD) != 0;
|
||||
if (!onSd) {
|
||||
destDir = mAppInstallDir;
|
||||
} else {
|
||||
String cachePath = getSdDir(pkgName);
|
||||
if (cachePath == null) {
|
||||
Log.e(TAG, "Secure container path for pkg: " + pkgName + " at location: " + cachePath +
|
||||
" not found");
|
||||
mLastScanError = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
||||
return null;
|
||||
}
|
||||
destDir = new File(cachePath);
|
||||
}
|
||||
destResourceFile = new File(destDir, pkgFileName);
|
||||
}
|
||||
destCodeFile = new File(destDir, pkgFileName);
|
||||
pkg.mPath = destCodeFile.getAbsolutePath();
|
||||
} else {
|
||||
pkg.mPath = pkg.mScanPath;
|
||||
destCodeFile = new File(pkg.mScanPath);
|
||||
destResourceFile = new File(pkg.mScanPath);
|
||||
}
|
||||
pkg.applicationInfo.sourceDir = destCodeFile.getAbsolutePath();
|
||||
pkg.applicationInfo.publicSourceDir = destResourceFile.getAbsolutePath();
|
||||
|
||||
SharedUserSetting suid = null;
|
||||
PackageSetting pkgSetting = null;
|
||||
|
||||
@@ -2394,7 +2433,6 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
pkg.applicationInfo.packageName,
|
||||
pkg.applicationInfo.processName,
|
||||
pkg.applicationInfo.uid);
|
||||
pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
|
||||
|
||||
File dataPath;
|
||||
if (mPlatformPackage == pkg) {
|
||||
@@ -2509,8 +2547,6 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
|
||||
pkg.mScanPath = path;
|
||||
|
||||
if ((scanMode&SCAN_NO_DEX) == 0) {
|
||||
@@ -2545,7 +2581,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
synchronized (mPackages) {
|
||||
// Add the new setting to mSettings
|
||||
mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
|
||||
mSettings.insertPackageSettingLP(pkgSetting, pkg);
|
||||
// Add the new setting to mPackages
|
||||
mPackages.put(pkg.applicationInfo.packageName, pkg);
|
||||
int N = pkg.providers.size();
|
||||
@@ -3714,7 +3750,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
if ((event&ADD_EVENTS) != 0) {
|
||||
PackageParser.Package p = mAppDirs.get(fullPathStr);
|
||||
if (p == null) {
|
||||
p = scanPackageLI(fullPath, fullPath, fullPath,
|
||||
p = scanPackageLI(fullPath,
|
||||
(mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
|
||||
PackageParser.PARSE_CHATTY |
|
||||
PackageParser.PARSE_MUST_BE_APK,
|
||||
@@ -3823,13 +3859,14 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
/*
|
||||
* Install a non-existing package.
|
||||
*/
|
||||
private void installNewPackageLI(String pkgName,
|
||||
File tmpPackageFile,
|
||||
String destFilePath, File destPackageFile, File destResourceFile,
|
||||
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
|
||||
private void installNewPackageLI(PackageParser.Package pkg,
|
||||
int parseFlags,
|
||||
int scanMode,
|
||||
String installerPackageName, PackageInstalledInfo res) {
|
||||
// Remember this for later, in case we need to rollback this install
|
||||
boolean dataDirExists;
|
||||
String pkgName = pkg.packageName;
|
||||
boolean onSd = (parseFlags & PackageParser.PARSE_ON_SDCARD) != 0;
|
||||
|
||||
if (useEncryptedFilesystemForPackage(pkg)) {
|
||||
dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
|
||||
@@ -3838,7 +3875,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
res.name = pkgName;
|
||||
synchronized(mPackages) {
|
||||
if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
|
||||
if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
|
||||
// Don't allow installation over an existing package with the same name.
|
||||
Log.w(TAG, "Attempt to re-install " + pkgName
|
||||
+ " without first uninstalling.");
|
||||
@@ -3846,32 +3883,37 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (destPackageFile.exists()) {
|
||||
// It's safe to do this because we know (from the above check) that the file
|
||||
// isn't currently used for an installed package.
|
||||
destPackageFile.delete();
|
||||
}
|
||||
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
|
||||
PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
|
||||
destResourceFile, pkg, 0,
|
||||
SCAN_MONITOR | SCAN_FORCE_DEX
|
||||
| SCAN_UPDATE_SIGNATURE
|
||||
| (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
|
||||
| (newInstall ? SCAN_NEW_INSTALL : 0));
|
||||
if (onSd) {
|
||||
// Create secure container mount point for package
|
||||
String cPath = createSdDir(new File(pkg.mScanPath), pkgName);
|
||||
if (cPath == null) {
|
||||
mLastScanError = res.returnCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
|
||||
if (newPackage == null) {
|
||||
Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
|
||||
Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
|
||||
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||
}
|
||||
} else {
|
||||
updateSettingsLI(pkgName, tmpPackageFile,
|
||||
destFilePath, destPackageFile,
|
||||
destResourceFile, pkg,
|
||||
newPackage,
|
||||
true,
|
||||
forwardLocked,
|
||||
File destPackageFile = new File(pkg.mPath);
|
||||
if (destPackageFile.exists()) {
|
||||
// It's safe to do this because we know (from the above check) that the file
|
||||
// isn't currently used for an installed package.
|
||||
destPackageFile.delete();
|
||||
}
|
||||
updateSettingsLI(newPackage,
|
||||
installerPackageName,
|
||||
res);
|
||||
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
|
||||
// Check if container can be finalized
|
||||
if(onSd && !finalizeSdDir(pkgName)) {
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
||||
}
|
||||
}
|
||||
// delete the partially installed application. the data directory will have to be
|
||||
// restored if it was already existing
|
||||
if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
|
||||
@@ -3885,15 +3927,19 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
res.removedInfo);
|
||||
}
|
||||
}
|
||||
if (onSd && res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
|
||||
// Destroy cache
|
||||
destroySdDir(pkgName);
|
||||
}
|
||||
}
|
||||
|
||||
private void replacePackageLI(String pkgName,
|
||||
File tmpPackageFile,
|
||||
String destFilePath, File destPackageFile, File destResourceFile,
|
||||
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
|
||||
private void replacePackageLI(PackageParser.Package pkg,
|
||||
int parseFlags,
|
||||
int scanMode,
|
||||
String installerPackageName, PackageInstalledInfo res) {
|
||||
|
||||
PackageParser.Package oldPackage;
|
||||
String pkgName = pkg.packageName;
|
||||
// First find the old package info and check signatures
|
||||
synchronized(mPackages) {
|
||||
oldPackage = mPackages.get(pkgName);
|
||||
@@ -3905,21 +3951,15 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
|
||||
if(sysPkg) {
|
||||
replaceSystemPackageLI(oldPackage,
|
||||
tmpPackageFile, destFilePath,
|
||||
destPackageFile, destResourceFile, pkg, forwardLocked,
|
||||
newInstall, installerPackageName, res);
|
||||
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
|
||||
} else {
|
||||
replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
|
||||
destPackageFile, destResourceFile, pkg, forwardLocked,
|
||||
newInstall, installerPackageName, res);
|
||||
replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
|
||||
File tmpPackageFile,
|
||||
String destFilePath, File destPackageFile, File destResourceFile,
|
||||
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
|
||||
PackageParser.Package pkg,
|
||||
int parseFlags, int scanMode,
|
||||
String installerPackageName, PackageInstalledInfo res) {
|
||||
PackageParser.Package newPackage = null;
|
||||
String pkgName = deletedPackage.packageName;
|
||||
@@ -3931,7 +3971,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
|
||||
}
|
||||
|
||||
int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
|
||||
parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
|
||||
// First delete the existing package while retaining the data directory
|
||||
if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
|
||||
res.removedInfo)) {
|
||||
@@ -3941,24 +3981,13 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
} else {
|
||||
// Successfully deleted the old package. Now proceed with re-installation
|
||||
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
|
||||
newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
|
||||
destResourceFile, pkg, parseFlags,
|
||||
SCAN_MONITOR | SCAN_FORCE_DEX
|
||||
| SCAN_UPDATE_SIGNATURE
|
||||
| (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
|
||||
| (newInstall ? SCAN_NEW_INSTALL : 0));
|
||||
newPackage = scanPackageLI(pkg, parseFlags, scanMode);
|
||||
if (newPackage == null) {
|
||||
Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
|
||||
Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
|
||||
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||
}
|
||||
} else {
|
||||
updateSettingsLI(pkgName, tmpPackageFile,
|
||||
destFilePath, destPackageFile,
|
||||
destResourceFile, pkg,
|
||||
newPackage,
|
||||
true,
|
||||
forwardLocked,
|
||||
}
|
||||
updateSettingsLI(newPackage,
|
||||
installerPackageName,
|
||||
res);
|
||||
updatedSettings = true;
|
||||
@@ -4028,13 +4057,12 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
|
||||
File tmpPackageFile,
|
||||
String destFilePath, File destPackageFile, File destResourceFile,
|
||||
PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
|
||||
PackageParser.Package pkg,
|
||||
int parseFlags, int scanMode,
|
||||
String installerPackageName, PackageInstalledInfo res) {
|
||||
PackageParser.Package newPackage = null;
|
||||
boolean updatedSettings = false;
|
||||
int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
|
||||
parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
|
||||
PackageParser.PARSE_IS_SYSTEM;
|
||||
String packageName = deletedPackage.packageName;
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
|
||||
@@ -4064,26 +4092,14 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
// Successfully disabled the old package. Now proceed with re-installation
|
||||
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
|
||||
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||
newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
|
||||
destResourceFile, pkg, parseFlags,
|
||||
SCAN_MONITOR | SCAN_FORCE_DEX
|
||||
| SCAN_UPDATE_SIGNATURE
|
||||
| (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
|
||||
| (newInstall ? SCAN_NEW_INSTALL : 0));
|
||||
newPackage = scanPackageLI(pkg, parseFlags, scanMode);
|
||||
if (newPackage == null) {
|
||||
Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
|
||||
Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
|
||||
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||
}
|
||||
} else {
|
||||
updateSettingsLI(packageName, tmpPackageFile,
|
||||
destFilePath, destPackageFile,
|
||||
destResourceFile, pkg,
|
||||
newPackage,
|
||||
true,
|
||||
forwardLocked,
|
||||
installerPackageName,
|
||||
res);
|
||||
updateSettingsLI(newPackage, installerPackageName, res);
|
||||
updatedSettings = true;
|
||||
}
|
||||
|
||||
@@ -4102,9 +4118,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
removePackageLI(newPackage, true);
|
||||
}
|
||||
// Add back the old system package
|
||||
scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
|
||||
oldPkgSetting.resourcePath,
|
||||
oldPkg, parseFlags,
|
||||
scanPackageLI(oldPkg, parseFlags,
|
||||
SCAN_MONITOR
|
||||
| SCAN_UPDATE_SIGNATURE);
|
||||
// Restore the old system information in Settings
|
||||
@@ -4119,14 +4133,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSettingsLI(String pkgName, File tmpPackageFile,
|
||||
String destFilePath, File destPackageFile,
|
||||
File destResourceFile,
|
||||
PackageParser.Package pkg,
|
||||
PackageParser.Package newPackage,
|
||||
boolean replacingExistingPackage,
|
||||
boolean forwardLocked,
|
||||
private void updateSettingsLI(PackageParser.Package newPackage,
|
||||
String installerPackageName, PackageInstalledInfo res) {
|
||||
String pkgName = newPackage.packageName;
|
||||
synchronized (mPackages) {
|
||||
//write settings. the installStatus will be incomplete at this stage.
|
||||
//note that the new package setting would have already been
|
||||
@@ -4136,11 +4145,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
int retCode = 0;
|
||||
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
|
||||
retCode = mInstaller.movedex(tmpPackageFile.toString(),
|
||||
destPackageFile.toString());
|
||||
if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
|
||||
retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
|
||||
if (retCode != 0) {
|
||||
Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
|
||||
Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
return;
|
||||
}
|
||||
@@ -4148,22 +4156,25 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
// XXX There are probably some big issues here: upon doing
|
||||
// the rename, we have reached the point of no return (the
|
||||
// original .apk is gone!), so we can't fail. Yet... we can.
|
||||
if (!tmpPackageFile.renameTo(destPackageFile)) {
|
||||
Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
File scanFile = new File(newPackage.mScanPath);
|
||||
if (!scanFile.renameTo(new File(newPackage.mPath))) {
|
||||
Log.e(TAG, "Couldn't move package file: " + newPackage.mScanPath + " to: " + newPackage.mPath);
|
||||
// TODO rename should work. Workaround
|
||||
if (!FileUtils.copyFile(scanFile, new File(newPackage.mPath))) {
|
||||
Log.e(TAG, "Couldn't move package file to: " + newPackage.mPath);
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
} else {
|
||||
res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
|
||||
destResourceFile,
|
||||
forwardLocked);
|
||||
res.returnCode = setPermissionsLI(newPackage);
|
||||
if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
|
||||
return;
|
||||
} else {
|
||||
Log.d(TAG, "New package installed in " + destPackageFile);
|
||||
Log.d(TAG, "New package installed in " + newPackage.mPath);
|
||||
}
|
||||
}
|
||||
if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
|
||||
if (mInstaller != null) {
|
||||
mInstaller.rmdex(tmpPackageFile.getPath());
|
||||
mInstaller.rmdex(newPackage.mScanPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4180,11 +4191,6 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private File getFwdLockedResource(String pkgName) {
|
||||
final String publicZipFileName = pkgName + ".zip";
|
||||
return new File(mAppInstallDir, publicZipFileName);
|
||||
}
|
||||
|
||||
private File copyTempInstallFile(Uri pPackageURI,
|
||||
PackageInstalledInfo res) {
|
||||
File tmpPackageFile = createTempPackageFile();
|
||||
@@ -4246,46 +4252,29 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
private void installPackageLI(Uri pPackageURI,
|
||||
int pFlags, boolean newInstall, String installerPackageName,
|
||||
File tmpPackageFile, PackageInstalledInfo res) {
|
||||
String pkgName = null;
|
||||
boolean forwardLocked = false;
|
||||
boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
|
||||
boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
|
||||
boolean replacingExistingPackage = false;
|
||||
int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
|
||||
| (newInstall ? SCAN_NEW_INSTALL : 0);
|
||||
// Result object to be returned
|
||||
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
|
||||
|
||||
main_flow: try {
|
||||
pkgName = PackageParser.parsePackageName(
|
||||
tmpPackageFile.getAbsolutePath(), 0);
|
||||
if (pkgName == null) {
|
||||
Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||
break main_flow;
|
||||
}
|
||||
res.name = pkgName;
|
||||
//initialize some variables before installing pkg
|
||||
final String pkgFileName = pkgName + ".apk";
|
||||
final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
|
||||
? mDrmAppPrivateInstallDir
|
||||
: mAppInstallDir;
|
||||
final File destPackageFile = new File(destDir, pkgFileName);
|
||||
final String destFilePath = destPackageFile.getAbsolutePath();
|
||||
File destResourceFile;
|
||||
if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
|
||||
destResourceFile = getFwdLockedResource(pkgName);
|
||||
forwardLocked = true;
|
||||
} else {
|
||||
destResourceFile = destPackageFile;
|
||||
}
|
||||
// Retrieve PackageSettings and parse package
|
||||
int parseFlags = PackageParser.PARSE_CHATTY;
|
||||
int parseFlags = PackageParser.PARSE_CHATTY |
|
||||
(forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
|
||||
(onSd ? PackageParser.PARSE_ON_SDCARD : 0);
|
||||
parseFlags |= mDefParseFlags;
|
||||
PackageParser pp = new PackageParser(tmpPackageFile.getPath());
|
||||
pp.setSeparateProcesses(mSeparateProcesses);
|
||||
final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
|
||||
destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
|
||||
null, mMetrics, parseFlags);
|
||||
if (pkg == null) {
|
||||
res.returnCode = pp.getParseError();
|
||||
break main_flow;
|
||||
}
|
||||
String pkgName = res.name = pkg.packageName;
|
||||
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
|
||||
if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
|
||||
@@ -4306,17 +4295,11 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
if(replacingExistingPackage) {
|
||||
replacePackageLI(pkgName,
|
||||
tmpPackageFile,
|
||||
destFilePath, destPackageFile, destResourceFile,
|
||||
pkg, forwardLocked, newInstall, installerPackageName,
|
||||
res);
|
||||
replacePackageLI(pkg, parseFlags, scanMode,
|
||||
installerPackageName, res);
|
||||
} else {
|
||||
installNewPackageLI(pkgName,
|
||||
tmpPackageFile,
|
||||
destFilePath, destPackageFile, destResourceFile,
|
||||
pkg, forwardLocked, newInstall, installerPackageName,
|
||||
res);
|
||||
installNewPackageLI(pkg, parseFlags, scanMode,
|
||||
installerPackageName,res);
|
||||
}
|
||||
} finally {
|
||||
if (tmpPackageFile != null && tmpPackageFile.exists()) {
|
||||
@@ -4325,13 +4308,12 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private int setPermissionsLI(String pkgName,
|
||||
PackageParser.Package newPackage,
|
||||
String destFilePath,
|
||||
File destResourceFile,
|
||||
boolean forwardLocked) {
|
||||
private int setPermissionsLI(PackageParser.Package newPackage) {
|
||||
String pkgName = newPackage.packageName;
|
||||
int retCode;
|
||||
if (forwardLocked) {
|
||||
if ((newPackage.applicationInfo.flags
|
||||
& ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
|
||||
File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
|
||||
try {
|
||||
extractPublicFiles(newPackage, destResourceFile);
|
||||
} catch (IOException e) {
|
||||
@@ -4347,25 +4329,25 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
} else {
|
||||
final int filePermissions =
|
||||
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
|
||||
retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
|
||||
retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
|
||||
newPackage.applicationInfo.uid);
|
||||
}
|
||||
} else {
|
||||
final int filePermissions =
|
||||
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
|
||||
|FileUtils.S_IROTH;
|
||||
retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
|
||||
retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1, -1);
|
||||
}
|
||||
if (retCode != 0) {
|
||||
Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
|
||||
Log.e(TAG, "Couldn't set new package file permissions for " +
|
||||
newPackage.mPath
|
||||
+ ". The return code was: " + retCode);
|
||||
}
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
}
|
||||
|
||||
private boolean isForwardLocked(PackageParser.Package deletedPackage) {
|
||||
final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
|
||||
return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
|
||||
private boolean isForwardLocked(PackageParser.Package pkg) {
|
||||
return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
|
||||
}
|
||||
|
||||
private void extractPublicFiles(PackageParser.Package newPackage,
|
||||
@@ -4643,9 +4625,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
mSettings.enableSystemPackageLP(p.packageName);
|
||||
}
|
||||
// Install the system package
|
||||
PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
|
||||
PackageParser.Package newPkg = scanPackageLI(ps.codePath,
|
||||
PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
|
||||
SCAN_MONITOR);
|
||||
SCAN_MONITOR | SCAN_NO_PATHS);
|
||||
|
||||
if (newPkg == null) {
|
||||
Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
|
||||
@@ -4749,14 +4731,32 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
|
||||
return false;
|
||||
}
|
||||
boolean onSd = (p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0;
|
||||
// Mount sd container if needed
|
||||
if (onSd) {
|
||||
// TODO Better error handling from MountService api later
|
||||
mountSdDir(p.packageName, Process.SYSTEM_UID) ;
|
||||
}
|
||||
boolean ret = false;
|
||||
if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
Log.i(TAG, "Removing system package:"+p.packageName);
|
||||
// When an updated system application is deleted we delete the existing resources as well and
|
||||
// fall back to existing code in system partition
|
||||
return deleteSystemPackageLI(p, flags, outInfo);
|
||||
ret = deleteSystemPackageLI(p, flags, outInfo);
|
||||
} else {
|
||||
Log.i(TAG, "Removing non-system package:"+p.packageName);
|
||||
ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
|
||||
}
|
||||
Log.i(TAG, "Removing non-system package:"+p.packageName);
|
||||
return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
|
||||
if (ret && onSd) {
|
||||
// Post a delayed destroy on the container since there might
|
||||
// be active processes holding open file handles to package
|
||||
// resources which will get killed by the process killer when
|
||||
// destroying the container. This might even kill the current
|
||||
// process and crash the system. Delay the destroy a bit so
|
||||
// that the active processes get to handle the uninstall broadcasts.
|
||||
sendDelayedDestroySdDir(packageName);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void clearApplicationUserData(final String packageName,
|
||||
@@ -6343,22 +6343,23 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
return p;
|
||||
}
|
||||
|
||||
private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
|
||||
File codePath, File resourcePath) {
|
||||
private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
|
||||
p.pkg = pkg;
|
||||
String codePath = pkg.applicationInfo.sourceDir;
|
||||
String resourcePath = pkg.applicationInfo.publicSourceDir;
|
||||
// Update code path if needed
|
||||
if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
|
||||
if (!codePath.equalsIgnoreCase(p.codePathString)) {
|
||||
Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
|
||||
" changing from " + p.codePathString + " to " + codePath);
|
||||
p.codePath = codePath;
|
||||
p.codePathString = codePath.toString();
|
||||
p.codePath = new File(codePath);
|
||||
p.codePathString = codePath;
|
||||
}
|
||||
//Update resource path if needed
|
||||
if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
|
||||
if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
|
||||
Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
|
||||
" changing from " + p.resourcePathString + " to " + resourcePath);
|
||||
p.resourcePath = resourcePath;
|
||||
p.resourcePathString = resourcePath.toString();
|
||||
p.resourcePath = new File(resourcePath);
|
||||
p.resourcePathString = resourcePath;
|
||||
}
|
||||
// Update version code if needed
|
||||
if (pkg.mVersionCode != p.versionCode) {
|
||||
@@ -7432,4 +7433,110 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
|| packageSettings.enabledComponents.contains(componentInfo.name));
|
||||
}
|
||||
}
|
||||
|
||||
// ------- apps on sdcard specific code -------
|
||||
static final boolean DEBUG_SD_INSTALL = false;
|
||||
final private String mSdEncryptKey = "none";
|
||||
|
||||
private MountService getMountService() {
|
||||
return (MountService) ServiceManager.getService("mount");
|
||||
}
|
||||
|
||||
private String createSdDir(File tmpPackageFile, String pkgName) {
|
||||
// Create mount point via MountService
|
||||
MountService mountService = getMountService();
|
||||
long len = tmpPackageFile.length();
|
||||
int mbLen = (int) (len/(1024*1024));
|
||||
if ((len - (mbLen * 1024 * 1024)) > 0) {
|
||||
mbLen++;
|
||||
}
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
|
||||
String cachePath = null;
|
||||
// Remove any pending destroy messages
|
||||
mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
|
||||
try {
|
||||
cachePath = mountService.createSecureContainer(pkgName,
|
||||
mbLen,
|
||||
"vfat", mSdEncryptKey, Process.SYSTEM_UID);
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
|
||||
return cachePath;
|
||||
} catch(IllegalStateException e) {
|
||||
Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
|
||||
}
|
||||
// TODO just fail here and let the user delete later on.
|
||||
try {
|
||||
mountService.destroySecureContainer(pkgName);
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "Destroying cache for " + pkgName + ", cachePath =" + cachePath);
|
||||
} catch(IllegalStateException e) {
|
||||
Log.e(TAG, "Failed to destroy existing cache: " + e);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
cachePath = mountService.createSecureContainer(pkgName,
|
||||
mbLen,
|
||||
"vfat", mSdEncryptKey, Process.SYSTEM_UID);
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install again " + pkgName + ", cachePath =" + cachePath);
|
||||
return cachePath;
|
||||
} catch(IllegalStateException e) {
|
||||
Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String mountSdDir(String pkgName, int ownerUid) {
|
||||
try {
|
||||
return getMountService().mountSecureContainer(pkgName, mSdEncryptKey, ownerUid);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " exception : " + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getSdDir(String pkgName) {
|
||||
String cachePath = null;
|
||||
try {
|
||||
cachePath = getMountService().getSecureContainerPath(pkgName);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Failed to retrieve secure container path for pkg : " + pkgName + " with exception " + e);
|
||||
}
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
private boolean finalizeSdDir(String pkgName) {
|
||||
try {
|
||||
getMountService().finalizeSecureContainer(pkgName);
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean destroySdDir(String pkgName) {
|
||||
try {
|
||||
if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
|
||||
// Don't have to send message again
|
||||
mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
|
||||
}
|
||||
// We need to destroy right away
|
||||
getMountService().destroySecureContainer(pkgName);
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendDelayedDestroySdDir(String pkgName) {
|
||||
if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
|
||||
// Don't have to send message again
|
||||
return;
|
||||
}
|
||||
Message msg = mHandler.obtainMessage(DESTROY_SD_CONTAINER, pkgName);
|
||||
mHandler.sendMessageDelayed(msg, DESTROY_SD_CONTAINER_DELAY);
|
||||
}
|
||||
|
||||
public void updateExternalMediaStatus(boolean mediaStatus) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user