summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/MountService.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java107
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java409
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java16
-rw-r--r--services/core/java/com/android/server/pm/Settings.java40
6 files changed, 383 insertions, 202 deletions
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 456f1fb..a341c95 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -833,6 +833,9 @@ class MountService extends IMountService.Stub
vol.userId = UserHandle.USER_OWNER;
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
+ } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+ mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
+
} else {
Slog.d(TAG, "Skipping automatic mounting of " + vol);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 95d7a52..aafb7a9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -63,6 +63,8 @@ import android.os.RemoteException;
import android.os.SELinux;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -75,6 +77,8 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.Xml;
+import libcore.io.IoUtils;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.FastXmlSerializer;
@@ -82,8 +86,6 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
import com.google.android.collect.Sets;
-import libcore.io.IoUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -131,6 +133,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
private static final String ATTR_ORIGINATING_URI = "originatingUri";
private static final String ATTR_REFERRER_URI = "referrerUri";
private static final String ATTR_ABI_OVERRIDE = "abiOverride";
+ private static final String ATTR_VOLUME_UUID = "volumeUuid";
/** Automatically destroy sessions older than this */
private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
@@ -141,9 +144,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
private final Context mContext;
private final PackageManagerService mPm;
- private final AppOpsManager mAppOps;
- private final File mStagingDir;
+ private AppOpsManager mAppOps;
+ private StorageManager mStorage;
+
private final HandlerThread mInstallThread;
private final Handler mInstallHandler;
@@ -186,12 +190,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
};
- public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) {
+ public PackageInstallerService(Context context, PackageManagerService pm) {
mContext = context;
mPm = pm;
- mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-
- mStagingDir = stagingDir;
mInstallThread = new HandlerThread(TAG);
mInstallThread.start();
@@ -208,8 +209,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
synchronized (mSessions) {
readSessionsLocked();
+ final File internalStagingDir = buildInternalStagingDir();
final ArraySet<File> unclaimedStages = Sets.newArraySet(
- mStagingDir.listFiles(sStageFilter));
+ internalStagingDir.listFiles(sStageFilter));
final ArraySet<File> unclaimedIcons = Sets.newArraySet(
mSessionsDir.listFiles());
@@ -238,6 +240,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
}
+ public void systemReady() {
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mStorage = mContext.getSystemService(StorageManager.class);
+ }
+
public void onSecureContainersAvailable() {
synchronized (mSessions) {
final ArraySet<String> unclaimed = new ArraySet<>();
@@ -275,13 +282,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
@Deprecated
- public File allocateInternalStageDirLegacy() throws IOException {
+ public File allocateStageDirLegacy(String volumeUuid) throws IOException {
synchronized (mSessions) {
try {
final int sessionId = allocateSessionIdLocked();
mLegacySessions.put(sessionId, true);
- final File stageDir = buildInternalStageDir(sessionId);
- prepareInternalStageDir(stageDir);
+ final File stageDir = buildStageDir(volumeUuid, sessionId);
+ prepareStageDir(stageDir);
return stageDir;
} catch (IllegalStateException e) {
throw new IOException(e);
@@ -322,11 +329,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
Slog.w(TAG, "Abandoning old session first created at "
+ session.createdMillis);
valid = false;
- } else if (session.stageDir != null
- && !session.stageDir.exists()) {
- Slog.w(TAG, "Abandoning internal session with missing stage "
- + session.stageDir);
- valid = false;
} else {
valid = true;
}
@@ -378,6 +380,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI);
params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
+ params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
final File appIconFile = buildAppIconFile(sessionId);
if (appIconFile.exists()) {
@@ -448,6 +451,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri);
writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri);
writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
+ writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
// Persist app icon if changed since last written
final File appIconFile = buildAppIconFile(session.sessionId);
@@ -528,28 +532,40 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
}
- if (params.mode == SessionParams.MODE_FULL_INSTALL
- || params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+ switch (params.mode) {
+ case SessionParams.MODE_FULL_INSTALL:
+ case SessionParams.MODE_INHERIT_EXISTING:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid install mode: " + params.mode);
+ }
+
+ // If caller requested explicit location, sanity check it, otherwise
+ // resolve the best internal or adopted location.
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ if (!PackageHelper.fitsOnInternal(mContext, params.sizeBytes)) {
+ throw new IOException("No suitable internal storage available");
+ }
+
+ } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ if (!PackageHelper.fitsOnExternal(mContext, params.sizeBytes)) {
+ throw new IOException("No suitable external storage available");
+ }
+
+ } else {
+ // For now, installs to adopted media are treated as internal from
+ // an install flag point-of-view.
+ params.setInstallFlagsInternal();
+
// Resolve best location for install, based on combination of
// requested install flags, delta size, and manifest settings.
final long ident = Binder.clearCallingIdentity();
try {
- final int resolved = PackageHelper.resolveInstallLocation(mContext,
- params.appPackageName, params.installLocation, params.sizeBytes,
- params.installFlags);
-
- if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
- params.setInstallFlagsInternal();
- } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
- params.setInstallFlagsExternal();
- } else {
- throw new IOException("No storage with enough free space; res=" + resolved);
- }
+ params.volumeUuid = PackageHelper.resolveInstallVolume(mContext,
+ params.appPackageName, params.installLocation, params.sizeBytes);
} finally {
Binder.restoreCallingIdentity(ident);
}
- } else {
- throw new IllegalArgumentException("Invalid install mode: " + params.mode);
}
final int sessionId;
@@ -574,7 +590,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
File stageDir = null;
String stageCid = null;
if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- stageDir = buildInternalStageDir(sessionId);
+ stageDir = buildStageDir(params.volumeUuid, sessionId);
} else {
stageCid = buildExternalStageCid(sessionId);
}
@@ -673,11 +689,30 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
throw new IllegalStateException("Failed to allocate session ID");
}
- private File buildInternalStageDir(int sessionId) {
- return new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+ private File buildInternalStagingDir() {
+ return new File(Environment.getDataDirectory(), "app");
+ }
+
+ private File buildStagingDir(String volumeUuid) throws FileNotFoundException {
+ if (volumeUuid == null) {
+ return buildInternalStagingDir();
+ } else {
+ final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
+ if (vol != null && vol.type == VolumeInfo.TYPE_PRIVATE
+ && vol.state == VolumeInfo.STATE_MOUNTED) {
+ return new File(vol.path, "app");
+ } else {
+ throw new FileNotFoundException("Failed to find volume for UUID " + volumeUuid);
+ }
+ }
+ }
+
+ private File buildStageDir(String volumeUuid, int sessionId) throws FileNotFoundException {
+ final File stagingDir = buildStagingDir(volumeUuid);
+ return new File(stagingDir, "vmdl" + sessionId + ".tmp");
}
- static void prepareInternalStageDir(File stageDir) throws IOException {
+ static void prepareStageDir(File stageDir) throws IOException {
if (stageDir.exists()) {
throw new IOException("Session dir already exists: " + stageDir);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index cc1b3ad..09e990c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -25,7 +25,7 @@ import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
-import static com.android.server.pm.PackageInstallerService.prepareInternalStageDir;
+import static com.android.server.pm.PackageInstallerService.prepareStageDir;
import android.content.Context;
import android.content.Intent;
@@ -61,6 +61,9 @@ import android.util.ExceptionUtils;
import android.util.MathUtils;
import android.util.Slog;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
@@ -69,9 +72,6 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
-import libcore.io.IoUtils;
-import libcore.io.Libcore;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -892,7 +892,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
synchronized (mLock) {
if (!mPrepared) {
if (stageDir != null) {
- prepareInternalStageDir(stageDir);
+ prepareStageDir(stageDir);
} else if (stageCid != null) {
prepareExternalStageCid(stageCid, params.sizeBytes);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2ff1718..84dc748 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -43,11 +43,17 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIB
import static android.content.pm.PackageManager.INSTALL_FAILED_USER_RESTRICTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
+import static android.content.pm.PackageManager.INSTALL_INTERNAL;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
-import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
-import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.MOVE_EXTERNAL_MEDIA;
+import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
+import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
+import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
+import static android.content.pm.PackageManager.MOVE_INTERNAL;
import static android.content.pm.PackageParser.isApkFile;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
@@ -65,31 +71,7 @@ import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
import android.Manifest;
-import android.content.pm.IntentFilterVerificationInfo;
-import android.util.ArrayMap;
-
-import com.android.internal.R;
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.app.ResolverActivity;
-import com.android.internal.content.NativeLibraryHelper;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.os.IParcelFileDescriptorFactory;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastPrintWriter;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.EventLogTags;
-import com.android.server.IntentResolver;
-import com.android.server.LocalServices;
-import com.android.server.ServiceThread;
-import com.android.server.SystemConfig;
-import com.android.server.Watchdog;
-import com.android.server.pm.Settings.DatabaseVersion;
-import com.android.server.storage.DeviceStorageMonitorInternal;
-
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
-
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
@@ -119,6 +101,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.KeySet;
import android.content.pm.ManifestDigest;
import android.content.pm.PackageCleanItem;
@@ -127,10 +110,10 @@ import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
+import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser;
import android.content.pm.PackageStats;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
@@ -150,13 +133,9 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
-import android.os.storage.IMountService;
-import android.os.storage.StorageEventListener;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.os.Debug;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -172,6 +151,10 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.IMountService;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.security.KeyStore;
import android.security.SystemKeyStore;
import android.system.ErrnoException;
@@ -179,6 +162,7 @@ import android.system.Os;
import android.system.StructStat;
import android.text.TextUtils;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.DisplayMetrics;
@@ -193,6 +177,33 @@ import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.Display;
+import dalvik.system.DexFile;
+import dalvik.system.VMRuntime;
+
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
+import com.android.internal.R;
+import com.android.internal.app.IMediaContainerService;
+import com.android.internal.app.ResolverActivity;
+import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.os.IParcelFileDescriptorFactory;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.EventLogTags;
+import com.android.server.IntentResolver;
+import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
+import com.android.server.Watchdog;
+import com.android.server.pm.Settings.DatabaseVersion;
+import com.android.server.storage.DeviceStorageMonitorInternal;
+
+import org.xmlpull.v1.XmlSerializer;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
@@ -227,12 +238,6 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-import dalvik.system.DexFile;
-import dalvik.system.VMRuntime;
-
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
-
/**
* Keep track of all those .apks everywhere.
*
@@ -1539,9 +1544,14 @@ public class PackageManagerService extends IPackageManager.Stub {
private StorageEventListener mStorageListener = new StorageEventListener() {
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
- Slog.v(TAG, vol.toString());
+ if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+ if (vol.state == VolumeInfo.STATE_MOUNTED) {
+ loadPrivatePackages(vol);
+ } else if (vol.state == VolumeInfo.STATE_UNMOUNTING) {
+ unloadPrivatePackages(vol);
+ }
+ }
- // TODO: when private volume shows up, look for packages there too
if (vol.isPrimary() && vol.type == VolumeInfo.TYPE_PUBLIC) {
if (vol.state == VolumeInfo.STATE_MOUNTED) {
updateExternalMediaStatus(true, false);
@@ -2160,7 +2170,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mRequiredVerifierPackage = getRequiredVerifierLPr();
- mInstallerService = new PackageInstallerService(context, this, mAppInstallDir);
+ mInstallerService = new PackageInstallerService(context, this);
mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
@@ -8476,8 +8486,8 @@ public class PackageManagerService extends IPackageManager.Stub {
public void installPackage(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, VerificationParams verificationParams,
String packageAbiOverride) {
- installPackageAsUser(originPath, observer, installFlags, installerPackageName, verificationParams,
- packageAbiOverride, UserHandle.getCallingUserId());
+ installPackageAsUser(originPath, observer, installFlags, installerPackageName,
+ verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
}
@Override
@@ -8524,7 +8534,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, observer, installFlags,
- installerPackageName, verificationParams, user, packageAbiOverride);
+ installerPackageName, null, verificationParams, user, packageAbiOverride);
mHandler.sendMessage(msg);
}
@@ -8543,7 +8553,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, observer, params.installFlags,
- installerPackageName, verifParams, user, params.abiOverride);
+ installerPackageName, params.volumeUuid, verifParams, user, params.abiOverride);
mHandler.sendMessage(msg);
}
@@ -9345,19 +9355,21 @@ public class PackageManagerService extends IPackageManager.Stub {
final IPackageInstallObserver2 observer;
int installFlags;
final String installerPackageName;
+ final String volumeUuid;
final VerificationParams verificationParams;
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
- String installerPackageName, VerificationParams verificationParams, UserHandle user,
- String packageAbiOverride) {
+ String installerPackageName, String volumeUuid,
+ VerificationParams verificationParams, UserHandle user, String packageAbiOverride) {
super(user);
this.origin = origin;
this.observer = observer;
this.installFlags = installFlags;
this.installerPackageName = installerPackageName;
+ this.volumeUuid = volumeUuid;
this.verificationParams = verificationParams;
this.packageAbiOverride = packageAbiOverride;
}
@@ -9711,7 +9723,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* @param installFlags package installation flags
* @return true if should be installed on external storage
*/
- private static boolean installOnSd(int installFlags) {
+ private static boolean installOnExternalAsec(int installFlags) {
if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
return false;
}
@@ -9732,7 +9744,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private InstallArgs createInstallArgs(InstallParams params) {
- if (installOnSd(params.installFlags) || params.isForwardLocked()) {
+ if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
return new AsecInstallArgs(params);
} else {
return new FileInstallArgs(params);
@@ -9746,7 +9758,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private InstallArgs createInstallArgsForExisting(int installFlags, String codePath,
String resourcePath, String nativeLibraryRoot, String[] instructionSets) {
final boolean isInAsec;
- if (installOnSd(installFlags)) {
+ if (installOnExternalAsec(installFlags)) {
/* Apps on SD card are always in ASEC containers. */
isInAsec = true;
} else if (installForwardLocked(installFlags)
@@ -9762,7 +9774,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isInAsec) {
return new AsecInstallArgs(codePath, instructionSets,
- installOnSd(installFlags), installForwardLocked(installFlags));
+ installOnExternalAsec(installFlags), installForwardLocked(installFlags));
} else {
return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
instructionSets);
@@ -9777,6 +9789,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Always refers to PackageManager flags only
final int installFlags;
final String installerPackageName;
+ final String volumeUuid;
final ManifestDigest manifestDigest;
final UserHandle user;
final String abiOverride;
@@ -9787,12 +9800,13 @@ public class PackageManagerService extends IPackageManager.Stub {
/* nullable */ String[] instructionSets;
InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
- String installerPackageName, ManifestDigest manifestDigest, UserHandle user,
- String[] instructionSets, String abiOverride) {
+ String installerPackageName, String volumeUuid, ManifestDigest manifestDigest,
+ UserHandle user, String[] instructionSets, String abiOverride) {
this.origin = origin;
this.installFlags = installFlags;
this.observer = observer;
this.installerPackageName = installerPackageName;
+ this.volumeUuid = volumeUuid;
this.manifestDigest = manifestDigest;
this.user = user;
this.instructionSets = instructionSets;
@@ -9844,7 +9858,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return (installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
}
- protected boolean isExternal() {
+ protected boolean isExternalAsec() {
return (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
}
@@ -9891,8 +9905,8 @@ public class PackageManagerService extends IPackageManager.Stub {
/** New install */
FileInstallArgs(InstallParams params) {
super(params.origin, params.observer, params.installFlags,
- params.installerPackageName, params.getManifestDigest(), params.getUser(),
- null /* instruction sets */, params.packageAbiOverride);
+ params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
+ params.getUser(), null /* instruction sets */, params.packageAbiOverride);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -9901,7 +9915,7 @@ public class PackageManagerService extends IPackageManager.Stub {
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath,
String[] instructionSets) {
- super(OriginInfo.fromNothing(), null, 0, null, null, null, instructionSets, null);
+ super(OriginInfo.fromNothing(), null, 0, null, null, null, null, instructionSets, null);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
this.legacyNativeLibraryPath = (legacyNativeLibraryPath != null) ?
@@ -9925,7 +9939,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
try {
- final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
+ final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid);
codeFile = tempDir;
resourceFile = tempDir;
} catch (IOException e) {
@@ -9986,8 +10000,9 @@ public class PackageManagerService extends IPackageManager.Stub {
cleanUp();
return false;
} else {
+ final File targetDir = codeFile.getParentFile();
final File beforeCodeFile = codeFile;
- final File afterCodeFile = getNextCodePath(pkg.packageName);
+ final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName);
Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
try {
@@ -10137,16 +10152,15 @@ public class PackageManagerService extends IPackageManager.Stub {
/** New install */
AsecInstallArgs(InstallParams params) {
super(params.origin, params.observer, params.installFlags,
- params.installerPackageName, params.getManifestDigest(),
- params.getUser(), null /* instruction sets */,
- params.packageAbiOverride);
+ params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
+ params.getUser(), null /* instruction sets */, params.packageAbiOverride);
}
/** Existing install */
AsecInstallArgs(String fullCodePath, String[] instructionSets,
boolean isExternal, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, (isExternal ? INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+ | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
instructionSets, null);
// Hackily pretend we're still looking at a full code path
if (!fullCodePath.endsWith(RES_FILE_NAME)) {
@@ -10163,7 +10177,7 @@ public class PackageManagerService extends IPackageManager.Stub {
AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+ | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
instructionSets, null);
this.cid = cid;
setMountPath(PackageHelper.getSdDir(cid));
@@ -10178,7 +10192,7 @@ public class PackageManagerService extends IPackageManager.Stub {
abiOverride);
final File target;
- if (isExternal()) {
+ if (isExternalAsec()) {
target = new UserEnvironment(UserHandle.USER_OWNER).getExternalStorageDirectory();
} else {
target = Environment.getDataDirectory();
@@ -10207,7 +10221,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final String newMountPath = imcs.copyPackageToContainer(
- origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
+ origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternalAsec(),
isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
if (newMountPath != null) {
@@ -10488,11 +10502,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return prefix + idxStr;
}
- private File getNextCodePath(String packageName) {
+ private File getNextCodePath(File targetDir, String packageName) {
int suffix = 1;
File result;
do {
- result = new File(mAppInstallDir, packageName + "-" + suffix);
+ result = new File(targetDir, packageName + "-" + suffix);
suffix++;
} while (result.exists());
return result;
@@ -10556,9 +10570,9 @@ public class PackageManagerService extends IPackageManager.Stub {
/*
* Install a non-existing package.
*/
- private void installNewPackageLI(PackageParser.Package pkg,
- int parseFlags, int scanFlags, UserHandle user,
- String installerPackageName, PackageInstalledInfo res) {
+ private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
+ UserHandle user, String installerPackageName, String volumeUuid,
+ PackageInstalledInfo res) {
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
@@ -10587,7 +10601,7 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,
System.currentTimeMillis(), user);
- updateSettingsLI(newPackage, installerPackageName, null, null, res, user);
+ updateSettingsLI(newPackage, installerPackageName, volumeUuid, null, null, res, user);
// delete the partially installed application. the data directory will have to be
// restored if it was already existing
if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
@@ -10619,9 +10633,9 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
- private void replacePackageLI(PackageParser.Package pkg,
- int parseFlags, int scanFlags, UserHandle user,
- String installerPackageName, PackageInstalledInfo res) {
+ private void replacePackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
+ UserHandle user, String installerPackageName, String volumeUuid,
+ PackageInstalledInfo res) {
PackageParser.Package oldPackage;
String pkgName = pkg.packageName;
int[] allUsers;
@@ -10660,17 +10674,17 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
- user, allUsers, perUserInstalled, installerPackageName, res);
+ user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res);
} else {
replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
- user, allUsers, perUserInstalled, installerPackageName, res);
+ user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res);
}
}
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
- int[] allUsers, boolean[] perUserInstalled,
- String installerPackageName, PackageInstalledInfo res) {
+ int[] allUsers, boolean[] perUserInstalled, String installerPackageName,
+ String volumeUuid, PackageInstalledInfo res) {
String pkgName = deletedPackage.packageName;
boolean deletedPkg = true;
boolean updatedSettings = false;
@@ -10709,8 +10723,8 @@ public class PackageManagerService extends IPackageManager.Stub {
try {
final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags,
scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
- updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res,
- user);
+ updateSettingsLI(newPackage, installerPackageName, volumeUuid, allUsers,
+ perUserInstalled, res, user);
updatedSettings = true;
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
@@ -10735,10 +10749,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
File restoreFile = new File(deletedPackage.codePath);
// Parse old package
- boolean oldOnSd = isExternal(deletedPackage);
+ boolean oldExternal = isExternal(deletedPackage);
int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
(deletedPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0) |
- (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
+ (oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;
try {
scanPackageLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime, null);
@@ -10762,8 +10776,8 @@ public class PackageManagerService extends IPackageManager.Stub {
private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
- int[] allUsers, boolean[] perUserInstalled,
- String installerPackageName, PackageInstalledInfo res) {
+ int[] allUsers, boolean[] perUserInstalled, String installerPackageName,
+ String volumeUuid, PackageInstalledInfo res) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+ ", old=" + deletedPackage);
boolean disabledSystem = false;
@@ -10840,8 +10854,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res,
- user);
+ updateSettingsLI(newPackage, installerPackageName, volumeUuid, allUsers,
+ perUserInstalled, res, user);
updatedSettings = true;
}
@@ -10876,8 +10890,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
- int[] allUsers, boolean[] perUserInstalled,
- PackageInstalledInfo res, UserHandle user) {
+ String volumeUuid, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res,
+ UserHandle user) {
String pkgName = newPackage.packageName;
synchronized (mPackages) {
//write settings. the installStatus will be incomplete at this stage.
@@ -10935,6 +10949,7 @@ public class PackageManagerService extends IPackageManager.Stub {
res.pkg = newPackage;
mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
mSettings.setInstallerPackageName(pkgName, installerPackageName);
+ mSettings.setVolumeUuid(pkgName, volumeUuid);
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
//to update install status
mSettings.writeLPr();
@@ -10943,10 +10958,12 @@ public class PackageManagerService extends IPackageManager.Stub {
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
final int installFlags = args.installFlags;
- String installerPackageName = args.installerPackageName;
- File tmpPackageFile = new File(args.getCodePath());
- boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
- boolean onSd = ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0);
+ final String installerPackageName = args.installerPackageName;
+ final String volumeUuid = args.volumeUuid;
+ final File tmpPackageFile = new File(args.getCodePath());
+ final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
+ final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
+ || (args.volumeUuid != null));
boolean replace = false;
final int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
// Result object to be returned
@@ -10956,7 +10973,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Retrieve PackageSettings and parse package
final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
- | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
+ | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
@@ -11108,7 +11125,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
- if (systemApp && onSd) {
+ if (systemApp && onExternal) {
// Disable updates to system apps on sdcard
res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
"Cannot install updates to system apps on sdcard");
@@ -11134,10 +11151,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (replace) {
// Call replacePackageLI with SCAN_NO_DEX, since we already made dexopt
replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING | SCAN_NO_DEX, args.user,
- installerPackageName, res);
+ installerPackageName, volumeUuid, res);
} else {
installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
- args.user, installerPackageName, res);
+ args.user, installerPackageName, volumeUuid, res);
}
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -11265,7 +11282,9 @@ public class PackageManagerService extends IPackageManager.Stub {
private int packageFlagsToInstallFlags(PackageSetting ps) {
int installFlags = 0;
- if (isExternal(ps)) {
+ if (isExternal(ps) && TextUtils.isEmpty(ps.volumeUuid)) {
+ // This existing package was an external ASEC install when we have
+ // the external flag without a UUID
installFlags |= PackageManager.INSTALL_EXTERNAL;
}
if (ps.isForwardLocked()) {
@@ -12975,6 +12994,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Watch for external volumes that come and go over time
final StorageManager storage = mContext.getSystemService(StorageManager.class);
storage.registerListener(mStorageListener);
+
+ mInstallerService.systemReady();
}
@Override
@@ -13713,13 +13734,32 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
+ ArrayList<ApplicationInfo> infos, IIntentReceiver finishedReceiver) {
+ final int size = infos.size();
+ final String[] packageNames = new String[size];
+ final int[] packageUids = new int[size];
+ for (int i = 0; i < size; i++) {
+ final ApplicationInfo info = infos.get(i);
+ packageNames[i] = info.packageName;
+ packageUids[i] = info.uid;
+ }
+ sendResourcesChangedBroadcast(mediaStatus, replacing, packageNames, packageUids,
+ finishedReceiver);
+ }
+
+ private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
- int size = pkgList.size();
+ sendResourcesChangedBroadcast(mediaStatus, replacing,
+ pkgList.toArray(new String[pkgList.size()]), uidArr, finishedReceiver);
+ }
+
+ private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
+ String[] pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
+ int size = pkgList.length;
if (size > 0) {
// Send broadcasts here
Bundle extras = new Bundle();
- extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
- .toArray(new String[size]));
+ extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
if (uidArr != null) {
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
}
@@ -13762,8 +13802,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Parse package
int parseFlags = mDefParseFlags;
- if (args.isExternal()) {
- parseFlags |= PackageParser.PARSE_ON_SDCARD;
+ if (args.isExternalAsec()) {
+ parseFlags |= PackageParser.PARSE_EXTERNAL_STORAGE;
}
if (args.isFwdLocked()) {
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
@@ -13910,73 +13950,130 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- /** Binder call */
+ private void loadPrivatePackages(VolumeInfo vol) {
+ final ArrayList<ApplicationInfo> loaded = new ArrayList<>();
+ final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
+ synchronized (mPackages) {
+ final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
+ for (PackageSetting ps : packages) {
+ synchronized (mInstallLock) {
+ final PackageParser.Package pkg;
+ try {
+ pkg = scanPackageLI(ps.codePath, parseFlags, 0, 0, null);
+ loaded.add(pkg.applicationInfo);
+ } catch (PackageManagerException e) {
+ Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
+ }
+ }
+ }
+
+ // TODO: regrant any permissions that changed based since original install
+
+ mSettings.writeLPr();
+ }
+
+ Slog.d(TAG, "Loaded packages " + loaded);
+ sendResourcesChangedBroadcast(true, false, loaded, null);
+ }
+
+ private void unloadPrivatePackages(VolumeInfo vol) {
+ final ArrayList<ApplicationInfo> unloaded = new ArrayList<>();
+ synchronized (mPackages) {
+ final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
+ for (PackageSetting ps : packages) {
+ if (ps.pkg == null) continue;
+ synchronized (mInstallLock) {
+ final ApplicationInfo info = ps.pkg.applicationInfo;
+ final PackageRemovedInfo outInfo = new PackageRemovedInfo();
+ if (deletePackageLI(ps.name, null, false, null, null,
+ PackageManager.DELETE_KEEP_DATA, outInfo, false)) {
+ unloaded.add(info);
+ } else {
+ Slog.w(TAG, "Failed to unload " + ps.codePath);
+ }
+ }
+ }
+
+ mSettings.writeLPr();
+ }
+
+ Slog.d(TAG, "Unloaded packages " + unloaded);
+ sendResourcesChangedBroadcast(false, false, unloaded, null);
+ }
+
@Override
public void movePackage(final String packageName, final IPackageMoveObserver observer,
final int flags) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
- UserHandle user = new UserHandle(UserHandle.getCallingUserId());
- int returnCode = PackageManager.MOVE_SUCCEEDED;
- int currInstallFlags = 0;
- int newInstallFlags = 0;
+
+ final int installFlags;
+ if ((flags & MOVE_INTERNAL) != 0) {
+ installFlags = INSTALL_INTERNAL;
+ } else if ((flags & MOVE_EXTERNAL_MEDIA) != 0) {
+ installFlags = INSTALL_EXTERNAL;
+ } else {
+ throw new IllegalArgumentException("Unsupported move flags " + flags);
+ }
+
+ try {
+ movePackageInternal(packageName, null, installFlags, false, observer);
+ } catch (PackageManagerException e) {
+ Slog.d(TAG, "Failed to move " + packageName, e);
+ try {
+ observer.packageMoved(packageName, e.error);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ @Override
+ public void movePackageAndData(final String packageName, final String volumeUuid,
+ final IPackageMoveObserver observer) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
+ try {
+ movePackageInternal(packageName, volumeUuid, INSTALL_INTERNAL, true, observer);
+ } catch (PackageManagerException e) {
+ Slog.d(TAG, "Failed to move " + packageName, e);
+ try {
+ observer.packageMoved(packageName, e.error);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ private void movePackageInternal(final String packageName, String volumeUuid, int installFlags,
+ boolean andData, final IPackageMoveObserver observer) throws PackageManagerException {
+ final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
File codeFile = null;
String installerPackageName = null;
String packageAbiOverride = null;
+ // TOOD: move app private data before installing
+
// reader
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (pkg == null || ps == null) {
- returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
- } else {
- // Disable moving fwd locked apps and system packages
- if (pkg.applicationInfo != null && isSystemApp(pkg)) {
- Slog.w(TAG, "Cannot move system application");
- returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
- } else if (pkg.mOperationPending) {
- Slog.w(TAG, "Attempt to move package which has pending operations");
- returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
- } else {
- // Find install location first
- if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
- && (flags & PackageManager.MOVE_INTERNAL) != 0) {
- Slog.w(TAG, "Ambigous flags specified for move location.");
- returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
- } else {
- newInstallFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
- ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
- currInstallFlags = isExternal(pkg)
- ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
-
- if (newInstallFlags == currInstallFlags) {
- Slog.w(TAG, "No move required. Trying to move to same location");
- returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
- } else {
- if (pkg.isForwardLocked()) {
- currInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK;
- newInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK;
- }
- }
- }
- if (returnCode == PackageManager.MOVE_SUCCEEDED) {
- pkg.mOperationPending = true;
- }
- }
-
- codeFile = new File(pkg.codePath);
- installerPackageName = ps.installerPackageName;
- packageAbiOverride = ps.cpuAbiOverrideString;
+ throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
}
- }
- if (returnCode != PackageManager.MOVE_SUCCEEDED) {
- try {
- observer.packageMoved(packageName, returnCode);
- } catch (RemoteException ignored) {
+ if (pkg.applicationInfo.isSystemApp()) {
+ throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
+ "Cannot move system application");
+ } else if (pkg.mOperationPending) {
+ throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING,
+ "Attempt to move package which has pending operations");
}
- return;
+
+ // TODO: yell if already in desired location
+
+ pkg.mOperationPending = true;
+
+ codeFile = new File(pkg.codePath);
+ installerPackageName = ps.installerPackageName;
+ packageAbiOverride = ps.cpuAbiOverrideString;
}
final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {
@@ -14018,12 +14115,12 @@ public class PackageManagerService extends IPackageManager.Stub {
// Treat a move like reinstalling an existing app, which ensures that we
// process everythign uniformly, like unpacking native libraries.
- newInstallFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+ installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
final Message msg = mHandler.obtainMessage(INIT_COPY);
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
- msg.obj = new InstallParams(origin, installObserver, newInstallFlags,
- installerPackageName, null, user, packageAbiOverride);
+ msg.obj = new InstallParams(origin, installObserver, installFlags,
+ installerPackageName, volumeUuid, null, user, packageAbiOverride);
mHandler.sendMessage(msg);
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index daa6d64..f294b32 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
+import android.os.storage.VolumeInfo;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -108,8 +109,10 @@ abstract class PackageSettingBase extends SettingBase {
PackageSettingBase origPackage;
- /* package name of the app that installed this package */
+ /** Package name of the app that installed this package */
String installerPackageName;
+ /** UUID of {@link VolumeInfo} hosting this app */
+ String volumeUuid;
IntentFilterVerificationInfo verificationInfo;
@@ -161,6 +164,7 @@ abstract class PackageSettingBase extends SettingBase {
origPackage = base.origPackage;
installerPackageName = base.installerPackageName;
+ volumeUuid = base.volumeUuid;
keySetData = new PackageKeySetData(base.keySetData);
}
@@ -183,10 +187,18 @@ abstract class PackageSettingBase extends SettingBase {
installerPackageName = packageName;
}
- String getInstallerPackageName() {
+ public String getInstallerPackageName() {
return installerPackageName;
}
+ public void setVolumeUuid(String volumeUuid) {
+ this.volumeUuid = volumeUuid;
+ }
+
+ public String getVolumeUuid() {
+ return volumeUuid;
+ }
+
public void setInstallStatus(int newStatus) {
installStatus = newStatus;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6930965..6b7c35c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -42,6 +42,7 @@ import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.VolumeInfo;
import android.util.AtomicFile;
import android.text.TextUtils;
import android.util.LogPrinter;
@@ -53,6 +54,7 @@ import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.backup.PreferredActivityBackupHelper;
import com.android.server.pm.PackageManagerService.DumpState;
@@ -333,14 +335,20 @@ final class Settings {
}
}
- void setInstallerPackageName(String pkgName,
- String installerPkgName) {
+ void setInstallerPackageName(String pkgName, String installerPkgName) {
PackageSetting p = mPackages.get(pkgName);
- if(p != null) {
+ if (p != null) {
p.setInstallerPackageName(installerPkgName);
}
}
+ void setVolumeUuid(String pkgName, String volumeUuid) {
+ PackageSetting p = mPackages.get(pkgName);
+ if (p != null) {
+ p.setVolumeUuid(volumeUuid);
+ }
+ }
+
SharedUserSetting getSharedUserLPw(String name,
int pkgFlags, int pkgPrivateFlags, boolean create) {
SharedUserSetting s = mSharedUsers.get(name);
@@ -2066,6 +2074,9 @@ final class Settings {
if (pkg.installerPackageName != null) {
serializer.attribute(null, "installer", pkg.installerPackageName);
}
+ if (pkg.volumeUuid != null) {
+ serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
+ }
pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissions());
@@ -2908,6 +2919,7 @@ final class Settings {
String cpuAbiOverrideString = null;
String systemStr = null;
String installerPackageName = null;
+ String volumeUuid = null;
String uidError = null;
int pkgFlags = 0;
int pkgPrivateFlags = 0;
@@ -2945,6 +2957,7 @@ final class Settings {
}
}
installerPackageName = parser.getAttributeValue(null, "installer");
+ volumeUuid = parser.getAttributeValue(null, "volumeUuid");
systemStr = parser.getAttributeValue(null, "publicFlags");
if (systemStr != null) {
@@ -3093,6 +3106,7 @@ final class Settings {
if (packageSetting != null) {
packageSetting.uidError = "true".equals(uidError);
packageSetting.installerPackageName = installerPackageName;
+ packageSetting.volumeUuid = volumeUuid;
packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
packageSetting.primaryCpuAbiString = primaryCpuAbiString;
packageSetting.secondaryCpuAbiString = secondaryCpuAbiString;
@@ -3549,6 +3563,22 @@ final class Settings {
return null;
}
+ /**
+ * Return all {@link PackageSetting} that are actively installed on the
+ * given {@link VolumeInfo#fsUuid}.
+ */
+ List<PackageSetting> getVolumePackagesLPr(String volumeUuid) {
+ Preconditions.checkNotNull(volumeUuid);
+ ArrayList<PackageSetting> res = new ArrayList<>();
+ for (int i = 0; i < mPackages.size(); i++) {
+ final PackageSetting setting = mPackages.valueAt(i);
+ if (Objects.equals(volumeUuid, setting.volumeUuid)) {
+ res.add(setting);
+ }
+ }
+ return res;
+ }
+
static void printFlags(PrintWriter pw, int val, Object[] spec) {
pw.print("[ ");
for (int i=0; i<spec.length; i+=2) {
@@ -3755,6 +3785,10 @@ final class Settings {
pw.print(prefix); pw.print(" installerPackageName=");
pw.println(ps.installerPackageName);
}
+ if (ps.volumeUuid != null) {
+ pw.print(prefix); pw.print(" volumeUuid=");
+ pw.println(ps.volumeUuid);
+ }
pw.print(prefix); pw.print(" signatures="); pw.println(ps.signatures);
pw.print(prefix); pw.print(" installPermissionsFixed=");
pw.print(ps.installPermissionsFixed);