Mount/Unmount secure containers
Persist flags in PackageSetting. Flags are relevant to ApplicationInfo.FLAG_SYSTEM, Application.FLAG_ON_SDCARD, ApplicationInfo.FLAG_FORWARD_LOCK. New pm command to simulate mount/unmount in Pm. This will be removed when MountService/vold event generation gets fixed. Calls from MountService into PackageManager when media gets mounted/unmounted. Scan the packages and grant permissions when the sdcard gets mounted. This api might change again.
This commit is contained in:
@ -92,6 +92,11 @@ public final class Pm {
|
||||
return;
|
||||
}
|
||||
|
||||
if ("mountsd".equals(op)) {
|
||||
runMountSd();
|
||||
return;
|
||||
}
|
||||
|
||||
if ("uninstall".equals(op)) {
|
||||
runUninstall();
|
||||
return;
|
||||
@ -637,6 +642,37 @@ public final class Pm {
|
||||
}
|
||||
}
|
||||
|
||||
private void runMountSd() {
|
||||
String opt;
|
||||
boolean mount = false;
|
||||
while ((opt=nextOption()) != null) {
|
||||
if (opt.equals("-m")) {
|
||||
String mountStr = nextOptionData();
|
||||
if (mountStr == null) {
|
||||
System.err.println("Error: no value specified for -m");
|
||||
showUsage();
|
||||
return;
|
||||
}
|
||||
if ("true".equalsIgnoreCase(mountStr)) {
|
||||
mount = true;
|
||||
} else if ("false".equalsIgnoreCase(mountStr)) {
|
||||
mount = false;
|
||||
} else {
|
||||
System.err.println("Error: no value specified for -m");
|
||||
showUsage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
mPm.updateExternalMediaStatus(mount);
|
||||
} catch (RemoteException e) {
|
||||
System.err.println(e.toString());
|
||||
System.err.println(PM_NOT_RUNNING_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
|
||||
boolean finished;
|
||||
boolean result;
|
||||
@ -826,6 +862,7 @@ public final class Pm {
|
||||
System.err.println(" pm path PACKAGE");
|
||||
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] PATH");
|
||||
System.err.println(" pm uninstall [-k] PACKAGE");
|
||||
System.err.println(" pm mountsd [-m true/false]");
|
||||
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
|
||||
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
|
||||
System.err.println("");
|
||||
@ -862,6 +899,9 @@ public final class Pm {
|
||||
System.err.println(" -k: keep the data and cache directories around.");
|
||||
System.err.println("after the package removal.");
|
||||
System.err.println("");
|
||||
System.err.println("The mountsd command simulates mounting/unmounting sdcard.Options:");
|
||||
System.err.println(" -m: true or false.");
|
||||
System.err.println("");
|
||||
System.err.println("The enable and disable commands change the enabled state of");
|
||||
System.err.println("a given package or component (written as \"package/class\").");
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.IMountService;
|
||||
import android.os.Environment;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UEventObserver;
|
||||
import android.os.Handler;
|
||||
@ -131,6 +132,8 @@ class MountService extends IMountService.Stub
|
||||
|
||||
private String mLegacyState = Environment.MEDIA_REMOVED;
|
||||
|
||||
private PackageManagerService mPms;
|
||||
|
||||
/**
|
||||
* Constructs a new MountService instance
|
||||
*
|
||||
@ -139,6 +142,7 @@ class MountService extends IMountService.Stub
|
||||
public MountService(Context context) {
|
||||
mContext = context;
|
||||
|
||||
mPms = (PackageManagerService) ServiceManager.getService("package");
|
||||
// Register a BOOT_COMPLETED handler so that we can start
|
||||
// our NativeDaemonConnector. We defer the startup so that we don't
|
||||
// start processing events before we ought-to
|
||||
@ -509,6 +513,8 @@ class MountService extends IMountService.Stub
|
||||
void handlePossibleExplicitUnmountBroadcast(String path) {
|
||||
if (mMounted) {
|
||||
mMounted = false;
|
||||
// Update media status on PackageManagerService to unmount packages on sdcard
|
||||
mPms.updateExternalMediaStatus(false);
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED,
|
||||
Uri.parse("file://" + path));
|
||||
mContext.sendBroadcast(intent);
|
||||
@ -739,6 +745,8 @@ class MountService extends IMountService.Stub
|
||||
|
||||
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
|
||||
|
||||
// Update media status on PackageManagerService to unmount packages on sdcard
|
||||
mPms.updateExternalMediaStatus(false);
|
||||
if (mShowSafeUnmountNotificationWhenUnmounted) {
|
||||
setMediaStorageNotification(
|
||||
com.android.internal.R.string.ext_media_safe_unmount_notification_title,
|
||||
@ -800,6 +808,8 @@ class MountService extends IMountService.Stub
|
||||
void notifyMediaMounted(String path, boolean readOnly) {
|
||||
updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
|
||||
|
||||
// Update media status on PackageManagerService to mount packages on sdcard
|
||||
mPms.updateExternalMediaStatus(true);
|
||||
setMediaStorageNotification(0, 0, 0, false, false, null);
|
||||
updateUsbMassStorageNotification(false, false);
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,
|
||||
|
@ -4753,13 +4753,18 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
ret = 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);
|
||||
if (deleteCodeAndResources) {
|
||||
// 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);
|
||||
} else {
|
||||
// Just unmount the directory
|
||||
unMountSdDir(packageName);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -5866,7 +5871,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
HashSet<String> loadedPermissions = new HashSet<String>();
|
||||
|
||||
GrantedPermissions(int pkgFlags) {
|
||||
this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
|
||||
this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
|
||||
(pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
|
||||
(pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6672,9 +6679,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
||||
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
||||
}
|
||||
serializer.attribute(null, "system",
|
||||
(pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
|
||||
? "true" : "false");
|
||||
serializer.attribute(null, "flags",
|
||||
Integer.toString(pkg.pkgFlags));
|
||||
serializer.attribute(null, "ts", pkg.getTimeStampStr());
|
||||
serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
|
||||
if (pkg.sharedUser == null) {
|
||||
@ -7065,16 +7071,24 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
systemStr = parser.getAttributeValue(null, "system");
|
||||
installerPackageName = parser.getAttributeValue(null, "installer");
|
||||
|
||||
systemStr = parser.getAttributeValue(null, "flags");
|
||||
if (systemStr != null) {
|
||||
if ("true".equals(systemStr)) {
|
||||
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
|
||||
try {
|
||||
pkgFlags = Integer.parseInt(systemStr);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
} else {
|
||||
// Old settings that don't specify system... just treat
|
||||
// them as system, good enough.
|
||||
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
|
||||
// For backward compatibility
|
||||
systemStr = parser.getAttributeValue(null, "system");
|
||||
if (systemStr != null) {
|
||||
pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
|
||||
} else {
|
||||
// Old settings that don't specify system... just treat
|
||||
// them as system, good enough.
|
||||
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
|
||||
}
|
||||
}
|
||||
timeStampStr = parser.getAttributeValue(null, "ts");
|
||||
if (timeStampStr != null) {
|
||||
@ -7443,6 +7457,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
static final boolean DEBUG_SD_INSTALL = false;
|
||||
final private String mSdEncryptKey = "AppsOnSD";
|
||||
final private String mSdEncryptAlg = "AES";
|
||||
private boolean mMediaMounted = false;
|
||||
|
||||
private MountService getMountService() {
|
||||
return (MountService) ServiceManager.getService("mount");
|
||||
@ -7518,6 +7533,11 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean unMountSdDir(String pkgName) {
|
||||
// STOPSHIP unmount directory
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getSdDir(String pkgName) {
|
||||
String cachePath = null;
|
||||
try {
|
||||
@ -7553,6 +7573,15 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getSecureContainerList() {
|
||||
try {
|
||||
return getMountService().getSecureContainerList();
|
||||
} catch (IllegalStateException e) {
|
||||
Log.i(TAG, "Failed to getSecureContainerList");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendDelayedDestroySdDir(String pkgName) {
|
||||
if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
|
||||
// Don't have to send message again
|
||||
@ -7562,7 +7591,63 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
mHandler.sendMessageDelayed(msg, DESTROY_SD_CONTAINER_DELAY);
|
||||
}
|
||||
|
||||
public void updateExternalMediaStatus(boolean mediaStatus) {
|
||||
// TODO
|
||||
public void updateExternalMediaStatus(final boolean mediaStatus) {
|
||||
if (mediaStatus == mMediaMounted) {
|
||||
return;
|
||||
}
|
||||
mMediaMounted = mediaStatus;
|
||||
// Queue up an async operation since the package installation may take a little while.
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mHandler.removeCallbacks(this);
|
||||
final String list[] = getSecureContainerList();
|
||||
if (list == null || list.length == 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
String mountPkg = list[i];
|
||||
// TODO compare with default package
|
||||
synchronized (mPackages) {
|
||||
PackageSetting ps = mSettings.mPackages.get(mountPkg);
|
||||
if (ps != null && (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
|
||||
if (mediaStatus) {
|
||||
String pkgPath = getSdDir(mountPkg);
|
||||
if (pkgPath == null) {
|
||||
continue;
|
||||
}
|
||||
pkgPath = ps.codePathString;
|
||||
int parseFlags = PackageParser.PARSE_CHATTY |
|
||||
PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
|
||||
PackageParser pp = new PackageParser(pkgPath);
|
||||
pp.setSeparateProcesses(mSeparateProcesses);
|
||||
final PackageParser.Package pkg = pp.parsePackage(new File(pkgPath),
|
||||
null, mMetrics, parseFlags);
|
||||
if (pkg == null) {
|
||||
Log.w(TAG, "Failed to install package : " + mountPkg + " from sd card");
|
||||
continue;
|
||||
}
|
||||
int scanMode = SCAN_MONITOR;
|
||||
// Scan the package
|
||||
if (scanPackageLI(pkg, parseFlags, scanMode) != null) {
|
||||
// Grant permissions
|
||||
grantPermissionsLP(pkg, false);
|
||||
// Persist settings
|
||||
mSettings.writeLP();
|
||||
} else {
|
||||
Log.i(TAG, "Failed to install package: " + mountPkg + " from sdcard");
|
||||
}
|
||||
} else {
|
||||
// Delete package
|
||||
PackageRemovedInfo outInfo = new PackageRemovedInfo();
|
||||
boolean res = deletePackageLI(mountPkg, false, PackageManager.DONT_DELETE_DATA, outInfo);
|
||||
if (!res) {
|
||||
Log.e(TAG, "Failed to delete pkg from sdcard : " + mountPkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user