summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/pm/PackageInstallerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java/com/android/server/pm/PackageInstallerService.java')
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java93
1 files changed, 72 insertions, 21 deletions
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 5fdfce4..682a38d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -30,8 +30,11 @@ import android.os.Binder;
import android.os.FileUtils;
import android.os.HandlerThread;
import android.os.Process;
+import android.os.SELinux;
import android.os.UserHandle;
import android.os.UserManager;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
@@ -42,6 +45,8 @@ import com.android.server.IoThread;
import com.google.android.collect.Sets;
import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
public class PackageInstallerService extends IPackageInstaller.Stub {
private static final String TAG = "PackageInstaller";
@@ -54,8 +59,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
private final AppOpsManager mAppOps;
private final File mStagingDir;
+ private final HandlerThread mInstallThread;
- private final HandlerThread mInstallThread = new HandlerThread(TAG);
private final Callback mCallback = new Callback();
@GuardedBy("mSessions")
@@ -63,27 +68,50 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
+ private static final FilenameFilter sStageFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("vmdl") && name.endsWith(".tmp");
+ }
+ };
+
public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) {
mContext = context;
mPm = pm;
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mStagingDir = stagingDir;
- mStagingDir.mkdirs();
+
+ mInstallThread = new HandlerThread(TAG);
+ mInstallThread.start();
synchronized (mSessions) {
readSessionsLocked();
// Clean up orphaned staging directories
- final ArraySet<String> dirs = Sets.newArraySet(mStagingDir.list());
+ final ArraySet<File> stages = Sets.newArraySet(mStagingDir.listFiles(sStageFilter));
for (int i = 0; i < mSessions.size(); i++) {
- dirs.remove(Integer.toString(mSessions.keyAt(i)));
+ final PackageInstallerSession session = mSessions.valueAt(i);
+ stages.remove(session.sessionStageDir);
+ }
+ for (File stage : stages) {
+ Slog.w(TAG, "Deleting orphan stage " + stage);
+ if (stage.isDirectory()) {
+ FileUtils.deleteContents(stage);
+ }
+ stage.delete();
}
- for (String dirName : dirs) {
- Slog.w(TAG, "Deleting orphan session " + dirName);
- final File dir = new File(mStagingDir, dirName);
- FileUtils.deleteContents(dir);
- dir.delete();
+ }
+ }
+
+ @Deprecated
+ public File allocateSessionDir() throws IOException {
+ synchronized (mSessions) {
+ try {
+ final int sessionId = allocateSessionIdLocked();
+ return prepareSessionStageDir(sessionId);
+ } catch (IllegalStateException e) {
+ throw new IOException(e);
}
}
}
@@ -110,11 +138,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
@Override
- public int createSession(int userId, String installerPackageName,
- PackageInstallerParams params) {
+ public int createSession(String installerPackageName, PackageInstallerParams params,
+ int userId) {
final int callingUid = Binder.getCallingUid();
mPm.enforceCrossUserPermission(callingUid, userId, false, TAG);
- mAppOps.checkPackage(callingUid, installerPackageName);
if (mPm.isUserRestricted(UserHandle.getUserId(callingUid),
UserManager.DISALLOW_INSTALL_APPS)) {
@@ -124,20 +151,21 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
if ((callingUid == Process.SHELL_UID) || (callingUid == 0)) {
params.installFlags |= INSTALL_FROM_ADB;
} else {
+ mAppOps.checkPackage(callingUid, installerPackageName);
+
params.installFlags &= ~INSTALL_FROM_ADB;
params.installFlags &= ~INSTALL_ALL_USERS;
params.installFlags |= INSTALL_REPLACE_EXISTING;
}
synchronized (mSessions) {
- final int sessionId = allocateSessionIdLocked();
final long createdMillis = System.currentTimeMillis();
- final File sessionDir = new File(mStagingDir, Integer.toString(sessionId));
- sessionDir.mkdirs();
+ final int sessionId = allocateSessionIdLocked();
+ final File sessionStageDir = prepareSessionStageDir(sessionId);
final PackageInstallerSession session = new PackageInstallerSession(mCallback, mPm,
sessionId, userId, installerPackageName, callingUid, params, createdMillis,
- sessionDir, mInstallThread.getLooper());
+ sessionStageDir, mInstallThread.getLooper());
mSessions.put(sessionId, session);
writeSessionsAsync();
@@ -166,8 +194,30 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
return mNextSessionId++;
}
+ private File prepareSessionStageDir(int sessionId) {
+ final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+
+ if (file.exists()) {
+ throw new IllegalStateException();
+ }
+
+ try {
+ Os.mkdir(file.getAbsolutePath(), 0755);
+ Os.chmod(file.getAbsolutePath(), 0755);
+ } catch (ErrnoException e) {
+ // This purposefully throws if directory already exists
+ throw new IllegalStateException("Failed to prepare session dir", e);
+ }
+
+ if (!SELinux.restorecon(file)) {
+ throw new IllegalStateException("Failed to prepare session dir");
+ }
+
+ return file;
+ }
+
@Override
- public int[] getSessions(int userId, String installerPackageName) {
+ public int[] getSessions(String installerPackageName, int userId) {
final int callingUid = Binder.getCallingUid();
mPm.enforceCrossUserPermission(callingUid, userId, false, TAG);
mAppOps.checkPackage(callingUid, installerPackageName);
@@ -187,13 +237,14 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
@Override
- public void uninstall(int userId, String basePackageName, IPackageDeleteObserver observer) {
- mPm.deletePackageAsUser(basePackageName, observer, userId, 0);
+ public void uninstall(String basePackageName, int flags, IPackageDeleteObserver observer,
+ int userId) {
+ mPm.deletePackageAsUser(basePackageName, observer, userId, flags);
}
@Override
- public void uninstallSplit(int userId, String basePackageName, String overlayName,
- IPackageDeleteObserver observer) {
+ public void uninstallSplit(String basePackageName, String overlayName, int flags,
+ IPackageDeleteObserver observer, int userId) {
// TODO: flesh out once PM has split support
throw new UnsupportedOperationException();
}