import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.util.Preconditions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
/**
* Represents a connection to {@code installd}. Allows multiple connect and
}
public synchronized String transact(String cmd) {
+ if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ }
+
if (!connect()) {
Slog.e(TAG, "connection failed");
return "-1";
}
}
- public int execute(String cmd) {
- if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
- + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ public void execute(String cmd, Object... args) throws InstallerException {
+ final String resRaw = executeForResult(cmd, args);
+ int res = -1;
+ try {
+ res = Integer.parseInt(resRaw);
+ } catch (NumberFormatException ignored) {
+ }
+ if (res != 0) {
+ throw new InstallerException(
+ "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
}
+ }
- String res = transact(cmd);
- try {
- return Integer.parseInt(res);
- } catch (NumberFormatException ex) {
- return -1;
+ public String executeForResult(String cmd, Object... args)
+ throws InstallerException {
+ final StringBuilder builder = new StringBuilder(cmd);
+ for (Object arg : args) {
+ String escaped;
+ if (arg == null) {
+ escaped = "";
+ } else {
+ escaped = String.valueOf(arg);
+ }
+ if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
+ throw new InstallerException(
+ "Invalid argument while executing " + cmd + " " + Arrays.toString(args));
+ }
+ if (TextUtils.isEmpty(escaped)) {
+ escaped = "!";
+ }
+ builder.append(' ').append(escaped);
}
+ return transact(builder.toString());
}
- public int dexopt(String apkPath, int uid, String instructionSet,
- int dexoptNeeded, int dexFlags) {
- return dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded,
- null /*outputPath*/, dexFlags);
+ public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
+ int dexFlags) throws InstallerException {
+ dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /* outputPath */, dexFlags);
}
- public int dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, String outputPath, int dexFlags) {
- StringBuilder builder = new StringBuilder("dexopt");
- builder.append(' ');
- builder.append(apkPath);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(instructionSet);
- builder.append(' ');
- builder.append(dexoptNeeded);
- builder.append(' ');
- builder.append(outputPath != null ? outputPath : "!");
- builder.append(' ');
- builder.append(dexFlags);
- return execute(builder.toString());
+ public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
+ int dexoptNeeded, String outputPath, int dexFlags) throws InstallerException {
+ execute("dexopt", apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
+ dexFlags);
}
private boolean connect() {
public void waitForConnection() {
for (;;) {
- if (execute("ping") >= 0) {
+ try {
+ execute("ping");
return;
+ } catch (InstallerException ignored) {
}
Slog.w(TAG, "installd not ready");
SystemClock.sleep(1000);
}
}
+
+ public static class InstallerException extends Exception {
+ public InstallerException(String detailMessage) {
+ super(detailMessage);
+ }
+ }
}
import android.util.Log;
import android.webkit.WebViewFactory;
+import com.android.internal.os.InstallerConnection.InstallerException;
+
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
import dalvik.system.VMRuntime;
dexoptNeeded, 0 /*dexFlags*/);
}
}
- } catch (IOException ioe) {
- throw new RuntimeException("Error starting system_server", ioe);
+ } catch (IOException | InstallerException e) {
+ throw new RuntimeException("Error starting system_server", e);
} finally {
installer.disconnect();
}
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
import com.android.internal.os.Zygote;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
Process.establishZygoteConnectionForAbi(abi);
final String instructionSet = VMRuntime.getInstructionSet(abi);
if (!completedIsas.contains(instructionSet)) {
- if (mInstaller.markBootComplete(VMRuntime.getInstructionSet(abi)) != 0) {
- Slog.e(TAG, "Unable to mark boot complete for abi: " + abi);
+ try {
+ mInstaller.markBootComplete(VMRuntime.getInstructionSet(abi));
+ } catch (InstallerException e) {
+ Slog.e(TAG, "Unable to mark boot complete for abi: " + abi, e);
}
completedIsas.add(instructionSet);
}
import android.content.Context;
import android.content.pm.PackageStats;
import android.os.Build;
-import android.text.TextUtils;
import android.util.Slog;
-import dalvik.system.VMRuntime;
-
import com.android.internal.os.InstallerConnection;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.server.SystemService;
+import dalvik.system.VMRuntime;
+
public final class Installer extends SystemService {
private static final String TAG = "Installer";
/** Run the application with the JIT compiler */
public static final int DEXOPT_USEJIT = 1 << 5;
+ public static final int FLAG_DE_STORAGE = 1 << 0;
+ public static final int FLAG_CE_STORAGE = 1 << 1;
+ public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 2;
+ public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 3;
+
private final InstallerConnection mInstaller;
public Installer(Context context) {
mInstaller.waitForConnection();
}
- private static String escapeNull(String arg) {
- if (TextUtils.isEmpty(arg)) {
- return "!";
- } else {
- if (arg.indexOf('\0') != -1 || arg.indexOf(' ') != -1) {
- throw new IllegalArgumentException(arg);
- }
- return arg;
- }
- }
-
- @Deprecated
- public int install(String name, int uid, int gid, String seinfo) {
- return install(null, name, uid, gid, seinfo);
- }
-
- public int install(String uuid, String name, int uid, int gid, String seinfo) {
- StringBuilder builder = new StringBuilder("install");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(gid);
- builder.append(' ');
- builder.append(seinfo != null ? seinfo : "!");
- return mInstaller.execute(builder.toString());
- }
-
- public int dexopt(String apkPath, int uid, String instructionSet,
- int dexoptNeeded, int dexFlags) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- return mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags);
- }
-
- public int dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, @Nullable String outputPath, int dexFlags) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
- return mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
- outputPath, dexFlags);
- }
-
- public int idmap(String targetApkPath, String overlayApkPath, int uid) {
- StringBuilder builder = new StringBuilder("idmap");
- builder.append(' ');
- builder.append(targetApkPath);
- builder.append(' ');
- builder.append(overlayApkPath);
- builder.append(' ');
- builder.append(uid);
- return mInstaller.execute(builder.toString());
- }
-
- public int movedex(String srcPath, String dstPath, String instructionSet) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("movedex");
- builder.append(' ');
- builder.append(srcPath);
- builder.append(' ');
- builder.append(dstPath);
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
- }
-
- public int rmdex(String codePath, String instructionSet) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("rmdex");
- builder.append(' ');
- builder.append(codePath);
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
- }
-
- /**
- * Removes packageDir or its subdirectory
- */
- public int rmPackageDir(String packageDir) {
- StringBuilder builder = new StringBuilder("rmpackagedir");
- builder.append(' ');
- builder.append(packageDir);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int remove(String name, int userId) {
- return remove(null, name, userId);
- }
-
- public int remove(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("remove");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int fixUid(String name, int uid, int gid) {
- return fixUid(null, name, uid, gid);
- }
-
- public int fixUid(String uuid, String name, int uid, int gid) {
- StringBuilder builder = new StringBuilder("fixuid");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(gid);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int deleteCacheFiles(String name, int userId) {
- return deleteCacheFiles(null, name, userId);
- }
-
- public int deleteCacheFiles(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("rmcache");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int deleteCodeCacheFiles(String name, int userId) {
- return deleteCodeCacheFiles(null, name, userId);
- }
-
- public int deleteCodeCacheFiles(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("rmcodecache");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int createUserData(String name, int uid, int userId, String seinfo) {
- return createUserData(null, name, uid, userId, seinfo);
- }
-
- public int createUserData(String uuid, String name, int uid, int userId, String seinfo) {
- StringBuilder builder = new StringBuilder("mkuserdata");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(userId);
- builder.append(' ');
- builder.append(seinfo != null ? seinfo : "!");
- return mInstaller.execute(builder.toString());
- }
-
- public int createUserConfig(int userId) {
- StringBuilder builder = new StringBuilder("mkuserconfig");
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int removeUserDataDirs(int userId) {
- return removeUserDataDirs(null, userId);
- }
-
- public int removeUserDataDirs(String uuid, int userId) {
- StringBuilder builder = new StringBuilder("rmuser");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- public int copyCompleteApp(String fromUuid, String toUuid, String packageName,
- String dataAppName, int appId, String seinfo) {
- StringBuilder builder = new StringBuilder("cpcompleteapp");
- builder.append(' ');
- builder.append(escapeNull(fromUuid));
- builder.append(' ');
- builder.append(escapeNull(toUuid));
- builder.append(' ');
- builder.append(packageName);
- builder.append(' ');
- builder.append(dataAppName);
- builder.append(' ');
- builder.append(appId);
- builder.append(' ');
- builder.append(seinfo);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int clearUserData(String name, int userId) {
- return clearUserData(null, name, userId);
+ public void createAppData(String uuid, String pkgname, int userid, int flags, int appid,
+ String seinfo) throws InstallerException {
+ mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo);
}
- public int clearUserData(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("rmuserdata");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
+ public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid,
+ String seinfo) throws InstallerException {
+ mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid,
+ seinfo);
}
- public int markBootComplete(String instructionSet) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("markbootcomplete");
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int freeCache(long freeStorageSize) {
- return freeCache(null, freeStorageSize);
+ public void clearAppData(String uuid, String pkgname, int userid, int flags)
+ throws InstallerException {
+ mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags);
}
- public int freeCache(String uuid, long freeStorageSize) {
- StringBuilder builder = new StringBuilder("freecache");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(String.valueOf(freeStorageSize));
- return mInstaller.execute(builder.toString());
+ public void destroyAppData(String uuid, String pkgname, int userid, int flags)
+ throws InstallerException {
+ mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags);
}
- @Deprecated
- public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
- String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats) {
- return getSizeInfo(null, pkgName, persona, apkPath, libDirPath, fwdLockApkPath, asecPath,
- instructionSets, pStats);
+ public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
+ String data_app_name, int appid, String seinfo) throws InstallerException {
+ mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name,
+ data_app_name, appid, seinfo);
}
- public int getSizeInfo(String uuid, String pkgName, int persona, String apkPath,
+ public void getAppSize(String uuid, String pkgname, int userid, int flags, String apkPath,
String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets,
- PackageStats pStats) {
+ PackageStats pStats) throws InstallerException {
for (String instructionSet : instructionSets) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
+ assertValidInstructionSet(instructionSet);
}
- StringBuilder builder = new StringBuilder("getsize");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(persona);
- builder.append(' ');
- builder.append(apkPath);
- builder.append(' ');
// TODO: Extend getSizeInfo to look at the full subdirectory tree,
// not just the first level.
- builder.append(libDirPath != null ? libDirPath : "!");
- builder.append(' ');
- builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
- builder.append(' ');
- builder.append(asecPath != null ? asecPath : "!");
- builder.append(' ');
// TODO: Extend getSizeInfo to look at *all* instrution sets, not
// just the primary.
- builder.append(instructionSets[0]);
-
- String s = mInstaller.transact(builder.toString());
- String res[] = s.split(" ");
+ final String rawRes = mInstaller.executeForResult("get_app_size", uuid, pkgname, userid,
+ flags, apkPath, libDirPath, fwdLockApkPath, asecPath, instructionSets[0]);
+ final String res[] = rawRes.split(" ");
if ((res == null) || (res.length != 5)) {
- return -1;
+ throw new InstallerException("Invalid size result: " + rawRes);
}
try {
pStats.codeSize = Long.parseLong(res[1]);
pStats.dataSize = Long.parseLong(res[2]);
pStats.cacheSize = Long.parseLong(res[3]);
pStats.externalCodeSize = Long.parseLong(res[4]);
- return Integer.parseInt(res[0]);
} catch (NumberFormatException e) {
- return -1;
+ throw new InstallerException("Invalid size result: " + rawRes);
}
}
- public int moveFiles() {
- return mInstaller.execute("movefiles");
+ public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
+ int dexFlags) throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags);
}
- @Deprecated
- public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId) {
- return linkNativeLibraryDirectory(null, dataPath, nativeLibPath32, userId);
+ public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
+ int dexoptNeeded, @Nullable String outputPath, int dexFlags)
+ throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
+ outputPath, dexFlags);
}
- /**
- * Links the 32 bit native library directory in an application's data directory to the
- * real location for backward compatibility. Note that no such symlink is created for
- * 64 bit shared libraries.
- *
- * @return -1 on error
- */
- public int linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
- int userId) {
- if (dataPath == null) {
- Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
- return -1;
- } else if (nativeLibPath32 == null) {
- Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
- return -1;
- }
+ public void idmap(String targetApkPath, String overlayApkPath, int uid)
+ throws InstallerException {
+ mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
+ }
- StringBuilder builder = new StringBuilder("linklib");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(dataPath);
- builder.append(' ');
- builder.append(nativeLibPath32);
- builder.append(' ');
- builder.append(userId);
-
- return mInstaller.execute(builder.toString());
+ public void rmdex(String codePath, String instructionSet) throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.execute("rmdex", codePath, instructionSet);
}
- @Deprecated
- public boolean restoreconData(String pkgName, String seinfo, int uid) {
- return restoreconData(null, pkgName, seinfo, uid);
+ public void rmPackageDir(String packageDir) throws InstallerException {
+ mInstaller.execute("rmpackagedir", packageDir);
}
- public boolean restoreconData(String uuid, String pkgName, String seinfo, int uid) {
- StringBuilder builder = new StringBuilder("restorecondata");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(seinfo != null ? seinfo : "!");
- builder.append(' ');
- builder.append(uid);
- return (mInstaller.execute(builder.toString()) == 0);
+ public void createUserConfig(int userid) throws InstallerException {
+ mInstaller.execute("mkuserconfig", userid);
}
- public int createOatDir(String oatDir, String dexInstructionSet) {
- StringBuilder builder = new StringBuilder("createoatdir");
- builder.append(' ');
- builder.append(oatDir);
- builder.append(' ');
- builder.append(dexInstructionSet);
- return mInstaller.execute(builder.toString());
+ public void removeUserDataDirs(String uuid, int userid) throws InstallerException {
+ mInstaller.execute("rmuser", uuid, userid);
}
+ public void markBootComplete(String instructionSet) throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.execute("markbootcomplete", instructionSet);
+ }
+
+ public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
+ mInstaller.execute("freecache", uuid, freeStorageSize);
+ }
- public int linkFile(String relativePath, String fromBase, String toBase) {
- StringBuilder builder = new StringBuilder("linkfile");
- builder.append(' ');
- builder.append(relativePath);
- builder.append(' ');
- builder.append(fromBase);
- builder.append(' ');
- builder.append(toBase);
- return mInstaller.execute(builder.toString());
+ public void moveFiles() throws InstallerException {
+ mInstaller.execute("movefiles");
}
/**
- * Returns true iff. {@code instructionSet} is a valid instruction set.
+ * Links the 32 bit native library directory in an application's data
+ * directory to the real location for backward compatibility. Note that no
+ * such symlink is created for 64 bit shared libraries.
*/
- private static boolean isValidInstructionSet(String instructionSet) {
- if (instructionSet == null) {
- return false;
- }
+ public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
+ int userId) throws InstallerException {
+ mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId);
+ }
+ public void createOatDir(String oatDir, String dexInstructionSet)
+ throws InstallerException {
+ mInstaller.execute("createoatdir", oatDir, dexInstructionSet);
+ }
+
+ public void linkFile(String relativePath, String fromBase, String toBase)
+ throws InstallerException {
+ mInstaller.execute("linkfile", relativePath, fromBase, toBase);
+ }
+
+ private static void assertValidInstructionSet(String instructionSet)
+ throws InstallerException {
for (String abi : Build.SUPPORTED_ABIS) {
- if (instructionSet.equals(VMRuntime.getInstructionSet(abi))) {
- return true;
+ if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) {
+ return;
}
}
-
- return false;
+ throw new InstallerException("Invalid instruction set: " + instructionSet);
}
}
import android.util.Log;
import android.util.Slog;
+import com.android.internal.os.InstallerConnection.InstallerException;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
| (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
| DEXOPT_BOOTCOMPLETE;
- final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
- pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir, dexFlags);
-
- // Dex2oat might fail due to compiler / verifier errors.
- if (ret == 0) {
+ try {
+ mPackageManagerService.mInstaller.dexopt(path, sharedGid,
+ pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir,
+ dexFlags);
performedDexOpt = true;
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to dexopt", e);
}
}
}
File codePath = new File(pkg.codePath);
if (codePath.isDirectory()) {
File oatDir = getOatDir(codePath);
- mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
- dexInstructionSet);
+ try {
+ mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
+ dexInstructionSet);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to create oat dir", e);
+ return null;
+ }
return oatDir.getAbsolutePath();
}
return null;
for (File stage : unclaimedStages) {
Slog.w(TAG, "Deleting orphan stage " + stage);
synchronized (mPm.mInstallLock) {
- if (stage.isDirectory()) {
- mPm.mInstaller.rmPackageDir(stage.getAbsolutePath());
- } else {
- stage.delete();
- }
+ mPm.removeCodePathLI(stage);
}
}
}
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
throw new IOException("File: " + pathStr + " outside base: " + baseStr);
}
- private void createOatDirs(List<String> instructionSets, File fromDir) {
+ private void createOatDirs(List<String> instructionSets, File fromDir)
+ throws PackageManagerException {
for (String instructionSet : instructionSets) {
- mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ try {
+ mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ } catch (InstallerException e) {
+ throw PackageManagerException.from(e);
+ }
}
}
throws IOException {
for (File fromFile : fromFiles) {
final String relativePath = getRelativePath(fromFile, fromDir);
- final int ret = mPm.mInstaller.linkFile(relativePath, fromDir.getAbsolutePath(),
- toDir.getAbsolutePath());
-
- if (ret < 0) {
- // installd will log failure details.
+ try {
+ mPm.mInstaller.linkFile(relativePath, fromDir.getAbsolutePath(),
+ toDir.getAbsolutePath());
+ } catch (InstallerException e) {
throw new IOException("failed linkOrCreateDir(" + relativePath + ", "
- + fromDir + ", " + toDir + ")");
+ + fromDir + ", " + toDir + ")", e);
}
}
}
}
if (stageDir != null) {
- mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ try {
+ mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ } catch (InstallerException ignored) {
+ }
}
if (stageCid != null) {
PackageHelper.destroySdDir(stageCid);
package com.android.server.pm;
+import android.content.pm.PackageManager;
import android.content.pm.PackageParser.PackageParserException;
+import com.android.internal.os.InstallerConnection.InstallerException;
+
/** {@hide} */
public class PackageManagerException extends Exception {
public final int error;
throws PackageManagerException {
throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
}
+
+ public static PackageManagerException from(InstallerException e)
+ throws PackageManagerException {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+ e.getMessage(), e.getCause());
+ }
}
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.os.IParcelFileDescriptorFactory;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
- } catch (IOException e) {
+ } catch (IOException | InstallerException e) {
Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ e.getMessage());
}
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
- mInstaller.moveFiles();
+ try {
+ mInstaller.moveFiles();
+ } catch (InstallerException e) {
+ logCriticalInfo(Log.WARN, "Update commands failed: " + e);
+ }
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
removeDataDirsLI(ps.volumeUuid, ps.name);
if (ps.codePath != null) {
- if (ps.codePath.isDirectory()) {
- mInstaller.rmPackageDir(ps.codePath.getAbsolutePath());
- } else {
- ps.codePath.delete();
- }
+ removeCodePathLI(ps.codePath);
}
if (ps.resourcePath != null && !ps.resourcePath.equals(ps.codePath)) {
if (ps.resourcePath.isDirectory()) {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- int retCode = -1;
+ boolean success = true;
synchronized (mInstallLock) {
- retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't clear application caches");
+ try {
+ mInstaller.freeCache(volumeUuid, freeStorageSize);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Couldn't clear application caches: " + e);
+ success = false;
}
}
if (observer != null) {
try {
- observer.onRemoveCompleted(null, (retCode >= 0));
+ observer.onRemoveCompleted(null, success);
} catch (RemoteException e) {
Slog.w(TAG, "RemoveException when invoking call back");
}
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- int retCode = -1;
+ boolean success = true;
synchronized (mInstallLock) {
- retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't clear application caches");
+ try {
+ mInstaller.freeCache(volumeUuid, freeStorageSize);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Couldn't clear application caches: " + e);
+ success = false;
}
}
if(pi != null) {
try {
// Callback via pending intent
- int code = (retCode >= 0) ? 1 : 0;
+ int code = success ? 1 : 0;
pi.sendIntent(null, code, null,
null, null);
} catch (SendIntentException e1) {
void freeStorage(String volumeUuid, long freeStorageSize) throws IOException {
synchronized (mInstallLock) {
- if (mInstaller.freeCache(volumeUuid, freeStorageSize) < 0) {
- throw new IOException("Failed to free enough space");
+ try {
+ mInstaller.freeCache(volumeUuid, freeStorageSize);
+ } catch (InstallerException e) {
+ throw new IOException("Failed to free enough space", e);
}
}
}
}
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
// TODO: generate idmap for split APKs
- if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid) != 0) {
+ try {
+ mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid);
+ } catch (InstallerException e) {
Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
+ opkg.baseCodePath);
return false;
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
- if (file.isDirectory()) {
- mInstaller.rmPackageDir(file.getAbsolutePath());
- } else {
- file.delete();
- }
+ removeCodePathLI(file);
}
}
}
private void createDataDirsLI(String volumeUuid, String packageName, int uid, String seinfo)
throws PackageManagerException {
- int res = mInstaller.install(volumeUuid, packageName, uid, uid, seinfo);
- if (res != 0) {
+ // TODO: triage flags as part of 26466827
+ final int appId = UserHandle.getAppId(uid);
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+
+ try {
+ final int[] users = sUserManager.getUserIds();
+ for (int user : users) {
+ mInstaller.createAppData(volumeUuid, packageName, user, flags, appId, seinfo);
+ }
+ } catch (InstallerException e) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to install " + packageName + ": " + res);
+ "Failed to prepare data directory", e);
}
+ }
+ private boolean removeDataDirsLI(String volumeUuid, String packageName) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+
+ boolean res = true;
final int[] users = sUserManager.getUserIds();
for (int user : users) {
- if (user != 0) {
- res = mInstaller.createUserData(volumeUuid, packageName,
- UserHandle.getUid(user, uid), user, seinfo);
- if (res != 0) {
- throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to createUserData " + packageName + ": " + res);
- }
+ try {
+ mInstaller.destroyAppData(volumeUuid, packageName, user, flags);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to delete data directory", e);
+ res = false;
}
}
+ return res;
}
- private int removeDataDirsLI(String volumeUuid, String packageName) {
- int[] users = sUserManager.getUserIds();
- int res = 0;
- for (int user : users) {
- int resInner = mInstaller.remove(volumeUuid, packageName, user);
- if (resInner < 0) {
- res = resInner;
+ void removeCodePathLI(File codePath) {
+ if (codePath.isDirectory()) {
+ try {
+ mInstaller.rmPackageDir(codePath.getAbsolutePath());
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to remove code path", e);
}
+ } else {
+ codePath.delete();
}
-
- return res;
}
- private int deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
- int[] users = sUserManager.getUserIds();
- int res = 0;
+ private void deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+
+ final int[] users = sUserManager.getUserIds();
for (int user : users) {
- int resInner = mInstaller.deleteCodeCacheFiles(volumeUuid, packageName, user);
- if (resInner < 0) {
- res = resInner;
+ try {
+ mInstaller.clearAppData(volumeUuid, packageName, user,
+ flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to delete code cache directory", e);
}
}
- return res;
}
private void addSharedLibraryLPw(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
final File dataPath = Environment.getDataUserCredentialEncryptedPackageDirectory(
pkg.volumeUuid, UserHandle.USER_SYSTEM, pkg.packageName);
+ // TOOD: switch to ensure various directories
+
boolean uidError = false;
if (dataPath.exists()) {
int currentUid = 0;
// If we have mismatched owners for the data path, we have a problem.
if (currentUid != pkg.applicationInfo.uid) {
boolean recovered = false;
- if (currentUid == 0) {
- // The directory somehow became owned by root. Wow.
- // This is probably because the system was stopped while
- // installd was in the middle of messing with its libs
- // directory. Ask installd to fix that.
- int ret = mInstaller.fixUid(pkg.volumeUuid, pkgName,
- pkg.applicationInfo.uid, pkg.applicationInfo.uid);
- if (ret >= 0) {
- recovered = true;
- String msg = "Package " + pkg.packageName
- + " unexpectedly changed to uid 0; recovered to " +
- + pkg.applicationInfo.uid;
- reportSettingsProblem(Log.WARN, msg);
- }
- }
- if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
- || (scanFlags&SCAN_BOOTING) != 0)) {
+ if (((parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0
+ || (scanFlags & SCAN_BOOTING) != 0)) {
// If this is a system app, we can at least delete its
// current data so the application will still work.
- int ret = removeDataDirsLI(pkg.volumeUuid, pkgName);
- if (ret >= 0) {
+ boolean res = removeDataDirsLI(pkg.volumeUuid, pkgName);
+ if (res) {
// TODO: Kill the processes first
// Old data gone!
String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
if (!recovered) {
mHasSystemUidErrors = true;
}
- } else if (!recovered) {
+ } else {
// If we allow this install to proceed, we will be broken.
// Abort, abort!
throw new PackageManagerException(INSTALL_FAILED_UID_CHANGED,
- "scanPackageLI");
+ "Expected data to be owned by UID " + pkg.applicationInfo.uid
+ + " but found " + currentUid);
}
if (!recovered) {
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
if (mShouldRestoreconData) {
Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
- mInstaller.restoreconData(pkg.volumeUuid, pkg.packageName,
- pkg.applicationInfo.seinfo, pkg.applicationInfo.uid);
+ // TODO: extend this to restorecon over all users
+ final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.restoreconAppData(pkg.volumeUuid, pkg.packageName,
+ UserHandle.USER_SYSTEM, flags, appId, pkg.applicationInfo.seinfo);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to restorecon " + pkg.packageName, e);
+ }
}
} else {
if (DEBUG_PACKAGE_SCANNING) {
if (!TextUtils.isEmpty(pkg.volumeUuid)) {
for (int userId : userIds) {
if (userId != UserHandle.USER_SYSTEM) {
- mInstaller.createUserData(pkg.volumeUuid, pkg.packageName,
- UserHandle.getUid(userId, pkg.applicationInfo.uid), userId,
- pkg.applicationInfo.seinfo);
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
+ try {
+ mInstaller.createAppData(pkg.volumeUuid, pkg.packageName, userId,
+ flags, appId, pkg.applicationInfo.seinfo);
+ } catch (InstallerException e) {
+ throw PackageManagerException.from(e);
+ }
}
}
}
try {
final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
for (int userId : userIds) {
- if (mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
- nativeLibPath, userId) < 0) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Failed linking native library dir (user=" + userId + ")");
+ try {
+ mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
+ nativeLibPath, userId);
+ } catch (InstallerException e) {
+ throw PackageManagerException.from(e);
}
}
} finally {
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi);
- mInstaller.rmdex(ps.codePathString,
- getDexCodeInstructionSet(getPreferredInstructionSet()));
+ try {
+ mInstaller.rmdex(ps.codePathString,
+ getDexCodeInstructionSet(getPreferredInstructionSet()));
+ } catch (InstallerException ignored) {
+ }
}
}
}
final long sizeBytes = mContainerService.calculateInstalledSize(
origin.resolvedPath, isForwardLocked(), packageAbiOverride);
- if (mInstaller.freeCache(null, sizeBytes + lowThreshold) >= 0) {
+ try {
+ mInstaller.freeCache(null, sizeBytes + lowThreshold);
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
installFlags, packageAbiOverride);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to free cache", e);
}
/*
String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String codePath : allCodePaths) {
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package at location " + codePath
- + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
+ try {
+ mInstaller.rmdex(codePath, dexCodeInstructionSet);
+ } catch (InstallerException ignored) {
}
}
}
return false;
}
- if (codeFile.isDirectory()) {
- mInstaller.rmPackageDir(codeFile.getAbsolutePath());
- } else {
- codeFile.delete();
- }
+ removeCodePathLI(codeFile);
if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
resourceFile.delete();
if (DEBUG_INSTALL) Slog.d(TAG, "Moving " + move.packageName + " from "
+ move.fromUuid + " to " + move.toUuid);
synchronized (mInstaller) {
- if (mInstaller.copyCompleteApp(move.fromUuid, move.toUuid, move.packageName,
- move.dataAppName, move.appId, move.seinfo) != 0) {
+ try {
+ mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
+ move.dataAppName, move.appId, move.seinfo);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to move app", e);
return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
}
}
synchronized (mInstallLock) {
// Clean up both app data and code
removeDataDirsLI(volumeUuid, move.packageName);
- if (codeFile.isDirectory()) {
- mInstaller.rmPackageDir(codeFile.getAbsolutePath());
- } else {
- codeFile.delete();
- }
+ removeCodePathLI(codeFile);
}
return true;
}
outInfo.removedAppId = appId;
outInfo.removedUsers = new int[] {removeUser};
}
- mInstaller.clearUserData(ps.volumeUuid, packageName, removeUser);
+ // TODO: triage flags as part of 26466827
+ final int installerFlags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.destroyAppData(ps.volumeUuid, packageName, removeUser, installerFlags);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to delete app data", e);
+ }
removeKeystoreDataIfNeeded(removeUser, appId);
schedulePackageCleaning(packageName, removeUser, false);
synchronized (mPackages) {
// Always delete data directories for package, even if we found no other
// record of app. This helps users recover from UID mismatches without
// resorting to a full data wipe.
- int retCode = mInstaller.clearUserData(pkg.volumeUuid, packageName, userId);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove cache files for package " + packageName);
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.clearAppData(pkg.volumeUuid, packageName, userId, flags);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Couldn't remove cache files for package " + packageName, e);
return false;
}
- final int appId = pkg.applicationInfo.uid;
+ final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
removeKeystoreDataIfNeeded(userId, appId);
// Create a native library symlink only if we have native libraries
if (pkg.applicationInfo.primaryCpuAbi != null &&
!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
- if (mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
- nativeLibPath, userId) < 0) {
- Slog.w(TAG, "Failed linking native library dir");
+ try {
+ mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
+ nativeLibPath, userId);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed linking native library dir", e);
return false;
}
}
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
- int retCode = mInstaller.deleteCacheFiles(p.volumeUuid, packageName, userId);
- if (retCode < 0) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.clearAppData(p.volumeUuid, packageName, userId,
+ flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+ } catch (InstallerException e) {
Slog.w(TAG, "Couldn't remove cache files for package "
- + packageName + " u" + userId);
+ + packageName + " u" + userId, e);
return false;
}
return true;
apkPath = p.baseCodePath;
}
- int res = mInstaller.getSizeInfo(p.volumeUuid, packageName, userHandle, apkPath,
- libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
- if (res < 0) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.getAppSize(p.volumeUuid, packageName, userHandle, flags, apkPath,
+ libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
+ } catch (InstallerException e) {
return false;
}
if (destroyUser) {
synchronized (mInstallLock) {
- mInstaller.removeUserDataDirs(volumeUuid, userId);
+ try {
+ mInstaller.removeUserDataDirs(volumeUuid, userId);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to clean up user dirs", e);
+ }
}
}
}
if (packageName != null) {
removeDataDirsLI(volumeUuid, packageName);
}
- if (file.isDirectory()) {
- mInstaller.rmPackageDir(file.getAbsolutePath());
- } else {
- file.delete();
- }
+ removeCodePathLI(file);
}
}
}
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
final String volumeUuid = vol.getFsUuid();
if (DEBUG_INSTALL) Slog.d(TAG, "Removing user data on volume " + volumeUuid);
- mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ try {
+ mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to remove user data", e);
+ }
}
synchronized (mPackages) {
removeUnusedPackagesLILPw(userManager, userHandle);
/** Called by UserManagerService */
void createNewUser(int userHandle) {
synchronized (mInstallLock) {
- mInstaller.createUserConfig(userHandle);
+ try {
+ mInstaller.createUserConfig(userHandle);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to create user config", e);
+ }
mSettings.createNewUserLI(this, mInstaller, userHandle);
}
synchronized (mPackages) {
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
int userHandle) {
String[] volumeUuids;
String[] names;
- int[] uids;
+ int[] appIds;
String[] seinfos;
int packagesCount;
synchronized (mPackages) {
packagesCount = packages.size();
volumeUuids = new String[packagesCount];
names = new String[packagesCount];
- uids = new int[packagesCount];
+ appIds = new int[packagesCount];
seinfos = new String[packagesCount];
Iterator<PackageSetting> packagesIterator = packages.iterator();
for (int i = 0; i < packagesCount; i++) {
// required args and call the installer after mPackages lock has been released
volumeUuids[i] = ps.volumeUuid;
names[i] = ps.name;
- uids[i] = UserHandle.getUid(userHandle, ps.appId);
+ appIds[i] = ps.appId;
seinfos[i] = ps.pkg.applicationInfo.seinfo;
}
}
if (names[i] == null) {
continue;
}
- installer.createUserData(volumeUuids[i], names[i], uids[i], userHandle, seinfos[i]);
+ // TODO: triage flags!
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ installer.createAppData(volumeUuids[i], names[i], userHandle, flags, appIds[i],
+ seinfos[i]);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to prepare app data", e);
+ }
}
synchronized (mPackages) {
applyDefaultPreferredAppsLPw(service, userHandle);