summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java4
-rw-r--r--core/java/android/content/pm/PackageInstaller.java65
-rw-r--r--core/java/android/content/pm/PackageParser.java2
-rw-r--r--core/java/android/os/storage/IMountService.java48
-rw-r--r--core/java/com/android/internal/content/NativeLibraryHelper.java49
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java81
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageHelperTests.java8
-rw-r--r--core/tests/coretests/src/android/os/storage/AsecTests.java2
-rw-r--r--libs/storage/IMountService.cpp2
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java52
-rw-r--r--services/core/java/com/android/server/MountService.java21
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java70
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java397
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java289
15 files changed, 717 insertions, 375 deletions
diff --git a/api/current.txt b/api/current.txt
index dfa95a0..093252d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8680,10 +8680,12 @@ package android.content.pm {
method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
method public void uninstall(java.lang.String, android.content.IntentSender);
field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
+ field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS";
field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
+ field public static final java.lang.String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
field public static final int STATUS_FAILURE = 1; // 0x1
field public static final int STATUS_FAILURE_ABORTED = 3; // 0x3
field public static final int STATUS_FAILURE_BLOCKED = 2; // 0x2
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 46d8ade..d9b40b1 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1004,6 +1004,10 @@ public final class Pm {
params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
} else if (opt.equals("-p")) {
params.mode = SessionParams.MODE_INHERIT_EXISTING;
+ params.appPackageName = nextOptionData();
+ if (params.appPackageName == null) {
+ throw new IllegalArgumentException("Missing inherit package name");
+ }
} else if (opt.equals("-S")) {
params.setSize(Long.parseLong(nextOptionData()));
} else if (opt.equals("--abi")) {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7419ebc..9afdbf7 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -45,6 +45,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -86,6 +87,8 @@ public class PackageInstaller {
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard
* against this.
+ * <p>
+ * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
@@ -95,21 +98,57 @@ public class PackageInstaller {
ACTION_CONFIRM_PERMISSIONS = "android.content.pm.action.CONFIRM_PERMISSIONS";
/**
- * An integer session ID.
+ * An integer session ID that an operation is working with.
*
- * @see #ACTION_SESSION_DETAILS
+ * @see Intent#getIntExtra(String, int)
*/
public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
+ /**
+ * Package name that an operation is working with.
+ *
+ * @see Intent#getStringExtra(String)
+ */
+ public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+
+ /**
+ * Current status of an operation. Will be one of
+ * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
+ * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
+ * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
+ * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
+ * {@link #STATUS_FAILURE_STORAGE}.
+ * <p>
+ * More information about a status may be available through additional
+ * extras; see the individual status documentation for details.
+ *
+ * @see Intent#getIntExtra(String, int)
+ */
public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
+
+ /**
+ * Detailed string representation of the status, including raw details that
+ * are useful for debugging.
+ *
+ * @see Intent#getStringExtra(String)
+ */
public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
/**
- * Package name relevant to a status.
+ * Another package name relevant to a status. This is typically the package
+ * responsible for causing an operation failure.
*
* @see Intent#getStringExtra(String)
*/
- public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+ public static final String
+ EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
+
+ /**
+ * Storage path relevant to a status.
+ *
+ * @see Intent#getStringExtra(String)
+ */
+ public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
/** {@hide} */
@Deprecated
@@ -153,8 +192,12 @@ public class PackageInstaller {
* The operation failed because it was blocked. For example, a device policy
* may be blocking the operation, a package verifier may have blocked the
* operation, or the app may be required for core system operation.
+ * <p>
+ * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
+ * specific package blocking the install.
*
* @see #EXTRA_STATUS_MESSAGE
+ * @see #EXTRA_OTHER_PACKAGE_NAME
*/
public static final int STATUS_FAILURE_BLOCKED = 2;
@@ -182,10 +225,11 @@ public class PackageInstaller {
* permission, incompatible certificates, etc. The user may be able to
* uninstall another app to fix the issue.
* <p>
- * The result may also contain {@link #EXTRA_PACKAGE_NAME} with the
+ * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
* specific package identified as the cause of the conflict.
*
* @see #EXTRA_STATUS_MESSAGE
+ * @see #EXTRA_OTHER_PACKAGE_NAME
*/
public static final int STATUS_FAILURE_CONFLICT = 5;
@@ -193,8 +237,12 @@ public class PackageInstaller {
* The operation failed because of storage issues. For example, the device
* may be running low on space, or external media may be unavailable. The
* user may be able to help free space or insert different external media.
+ * <p>
+ * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
+ * the storage device that caused the failure.
*
* @see #EXTRA_STATUS_MESSAGE
+ * @see #EXTRA_STORAGE_PATH
*/
public static final int STATUS_FAILURE_STORAGE = 6;
@@ -281,6 +329,13 @@ public class PackageInstaller {
* To succeed, the caller must be the current home app.
*/
public @NonNull List<SessionInfo> getAllSessions() {
+ final ApplicationInfo info = mContext.getApplicationInfo();
+ if ("com.google.android.googlequicksearchbox".equals(info.packageName)
+ && info.versionCode <= 300400070) {
+ Log.d(TAG, "Ignoring callback request from old prebuilt");
+ return Collections.EMPTY_LIST;
+ }
+
try {
return mInstaller.getAllSessions(mUserId);
} catch (RemoteException e) {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index eb8b762..142206a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -264,7 +264,7 @@ public class PackageParser {
public final boolean coreApp;
public final boolean multiArch;
- private PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
+ public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
String[] splitCodePaths) {
this.packageName = baseApk.packageName;
this.versionCode = baseApk.versionCode;
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 939cda9..d1fadd6 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -321,7 +321,7 @@ public interface IMountService extends IInterface {
* Mount a secure container with the specified key and owner UID.
* Returns an int consistent with MountServiceResultCode
*/
- public int mountSecureContainer(String id, String key, int ownerUid)
+ public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly)
throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -331,6 +331,7 @@ public interface IMountService extends IInterface {
_data.writeString(id);
_data.writeString(key);
_data.writeInt(ownerUid);
+ _data.writeInt(readOnly ? 1 : 0);
mRemote.transact(Stub.TRANSACTION_mountSecureContainer, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
@@ -834,6 +835,27 @@ public interface IMountService extends IInterface {
}
return _result;
}
+
+ @Override
+ public int resizeSecureContainer(String id, int sizeMb, String key)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ _data.writeInt(sizeMb);
+ _data.writeString(key);
+ mRemote.transact(Stub.TRANSACTION_resizeSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
}
private static final String DESCRIPTOR = "IMountService";
@@ -918,6 +940,8 @@ public interface IMountService extends IInterface {
static final int TRANSACTION_getField = IBinder.FIRST_CALL_TRANSACTION + 39;
+ static final int TRANSACTION_resizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 40;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1082,7 +1106,9 @@ public interface IMountService extends IInterface {
key = data.readString();
int ownerUid;
ownerUid = data.readInt();
- int resultCode = mountSecureContainer(id, key, ownerUid);
+ boolean readOnly;
+ readOnly = data.readInt() != 0;
+ int resultCode = mountSecureContainer(id, key, ownerUid, readOnly);
reply.writeNoException();
reply.writeInt(resultCode);
return true;
@@ -1308,6 +1334,19 @@ public interface IMountService extends IInterface {
reply.writeString(contents);
return true;
}
+ case TRANSACTION_resizeSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ int sizeMb;
+ sizeMb = data.readInt();
+ String key;
+ key = data.readString();
+ int resultCode = resizeSecureContainer(id, sizeMb, key);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -1405,7 +1444,8 @@ public interface IMountService extends IInterface {
* Mount a secure container with the specified key and owner UID. Returns an
* int consistent with MountServiceResultCode
*/
- public int mountSecureContainer(String id, String key, int ownerUid) throws RemoteException;
+ public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly)
+ throws RemoteException;
/**
* Mount external storage at given mount point. Returns an int consistent
@@ -1571,4 +1611,6 @@ public interface IMountService extends IInterface {
* @return contents of field
*/
public String getField(String field) throws RemoteException;
+
+ public int resizeSecureContainer(String id, int sizeMb, String key) throws RemoteException;
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 179d5e8..02f675c 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -25,6 +25,7 @@ import static android.system.OsConstants.S_IRWXU;
import static android.system.OsConstants.S_IXGRP;
import static android.system.OsConstants.S_IXOTH;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
@@ -51,9 +52,11 @@ import java.util.List;
*/
public class NativeLibraryHelper {
private static final String TAG = "NativeHelper";
-
private static final boolean DEBUG_NATIVE = false;
+ public static final String LIB_DIR_NAME = "lib";
+ public static final String LIB64_DIR_NAME = "lib64";
+
// Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
// that the cpuAbiOverride must be clear.
public static final String CLEAR_ABI_OVERRIDE = "-";
@@ -70,6 +73,7 @@ public class NativeLibraryHelper {
private volatile boolean mClosed;
final long[] apkHandles;
+ final boolean multiArch;
public static Handle create(File packageFile) throws IOException {
try {
@@ -81,14 +85,15 @@ public class NativeLibraryHelper {
}
public static Handle create(Package pkg) throws IOException {
- return create(pkg.getAllCodePaths());
+ return create(pkg.getAllCodePaths(),
+ (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0);
}
public static Handle create(PackageLite lite) throws IOException {
- return create(lite.getAllCodePaths());
+ return create(lite.getAllCodePaths(), lite.multiArch);
}
- private static Handle create(List<String> codePaths) throws IOException {
+ private static Handle create(List<String> codePaths, boolean multiArch) throws IOException {
final int size = codePaths.size();
final long[] apkHandles = new long[size];
for (int i = 0; i < size; i++) {
@@ -103,11 +108,12 @@ public class NativeLibraryHelper {
}
}
- return new Handle(apkHandles);
+ return new Handle(apkHandles, multiArch);
}
- Handle(long[] apkHandles) {
+ Handle(long[] apkHandles, boolean multiArch) {
this.apkHandles = apkHandles;
+ this.multiArch = multiArch;
mGuard.open("close");
}
@@ -159,8 +165,7 @@ public class NativeLibraryHelper {
* @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
* error code from that class if not
*/
- public static int copyNativeBinariesIfNeededLI(Handle handle, File sharedLibraryDir,
- String abi) {
+ public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
for (long apkHandle : handle.apkHandles) {
int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi);
if (res != INSTALL_SUCCEEDED) {
@@ -267,7 +272,7 @@ public class NativeLibraryHelper {
}
}
- private static long sumNativeBinaries(Handle handle, String[] abiList) {
+ private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) {
int abi = findSupportedAbi(handle, abiList);
if (abi >= 0) {
return sumNativeBinaries(handle, abiList[abi]);
@@ -276,7 +281,7 @@ public class NativeLibraryHelper {
}
}
- public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
+ public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot,
String[] abiList, boolean useIsaSubdir) throws IOException {
createNativeLibrarySubdir(libraryRoot);
@@ -300,7 +305,7 @@ public class NativeLibraryHelper {
subDir = libraryRoot;
}
- int copyRet = copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]);
+ int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
return copyRet;
}
@@ -309,10 +314,10 @@ public class NativeLibraryHelper {
return abi;
}
- public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
- String abiOverride, boolean multiArch) {
+ public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot,
+ String abiOverride) {
try {
- if (multiArch) {
+ if (handle.multiArch) {
// Warn if we've set an abiOverride for multi-lib packages..
// By definition, we need to copy both 32 and 64 bit libraries for
// such packages.
@@ -322,7 +327,7 @@ public class NativeLibraryHelper {
int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
- copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
@@ -332,7 +337,7 @@ public class NativeLibraryHelper {
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
- copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot,
Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
@@ -355,7 +360,7 @@ public class NativeLibraryHelper {
abiList = Build.SUPPORTED_32_BIT_ABIS;
}
- int copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, abiList,
+ int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList,
true /* use isa specific subdirs */);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
@@ -370,10 +375,10 @@ public class NativeLibraryHelper {
}
}
- public static long sumNativeBinaries(Handle handle, String abiOverride, boolean multiArch)
+ public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride)
throws IOException {
long sum = 0;
- if (multiArch) {
+ if (handle.multiArch) {
// Warn if we've set an abiOverride for multi-lib packages..
// By definition, we need to copy both 32 and 64 bit libraries for
// such packages.
@@ -382,11 +387,11 @@ public class NativeLibraryHelper {
}
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
- sum += sumNativeBinaries(handle, Build.SUPPORTED_32_BIT_ABIS);
+ sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
- sum += sumNativeBinaries(handle, Build.SUPPORTED_64_BIT_ABIS);
+ sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
}
} else {
String cpuAbiOverride = null;
@@ -403,7 +408,7 @@ public class NativeLibraryHelper {
abiList = Build.SUPPORTED_32_BIT_ABIS;
}
- sum += sumNativeBinaries(handle, abiList);
+ sum += sumNativeBinariesForSupportedAbi(handle, abiList);
}
return sum;
}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index a529cc3..c17f4ee 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -16,11 +16,14 @@
package com.android.internal.content;
+import static android.net.TrafficStats.MB_IN_BYTES;
+
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageParser.PackageLite;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
@@ -77,9 +80,10 @@ public class PackageHelper {
}
}
- public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid,
+ public static String createSdDir(long sizeBytes, String cid, String sdEncKey, int uid,
boolean isExternal) {
- // Create mount point via MountService
+ // Round up to nearest MB, plus another MB for filesystem overhead
+ final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
try {
IMountService mountService = getMountService();
@@ -102,19 +106,39 @@ public class PackageHelper {
return null;
}
- public static String mountSdDir(String cid, String key, int ownerUid) {
- try {
- int rc = getMountService().mountSecureContainer(cid, key, ownerUid);
- if (rc != StorageResultCode.OperationSucceeded) {
- Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc);
- return null;
+ public static boolean resizeSdDir(long sizeBytes, String cid, String sdEncKey) {
+ // Round up to nearest MB, plus another MB for filesystem overhead
+ final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
+ try {
+ IMountService mountService = getMountService();
+ int rc = mountService.resizeSecureContainer(cid, sizeMb, sdEncKey);
+ if (rc == StorageResultCode.OperationSucceeded) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "MountService running?");
}
- return getMountService().getSecureContainerPath(cid);
- } catch (RemoteException e) {
- Log.e(TAG, "MountService running?");
+ Log.e(TAG, "Failed to create secure container " + cid);
+ return false;
+ }
+
+ public static String mountSdDir(String cid, String key, int ownerUid) {
+ return mountSdDir(cid, key, ownerUid, true);
+ }
+
+ public static String mountSdDir(String cid, String key, int ownerUid, boolean readOnly) {
+ try {
+ int rc = getMountService().mountSecureContainer(cid, key, ownerUid, readOnly);
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc);
+ return null;
+ }
+ return getMountService().getSecureContainerPath(cid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "MountService running?");
+ }
+ return null;
}
- return null;
- }
public static boolean unMountSdDir(String cid) {
try {
@@ -400,6 +424,37 @@ public class PackageHelper {
}
}
+ public static long calculateInstalledSize(PackageLite pkg, boolean isForwardLocked,
+ String abiOverride) throws IOException {
+ NativeLibraryHelper.Handle handle = null;
+ try {
+ handle = NativeLibraryHelper.Handle.create(pkg);
+ return calculateInstalledSize(pkg, handle, isForwardLocked, abiOverride);
+ } finally {
+ IoUtils.closeQuietly(handle);
+ }
+ }
+
+ public static long calculateInstalledSize(PackageLite pkg, NativeLibraryHelper.Handle handle,
+ boolean isForwardLocked, String abiOverride) throws IOException {
+ long sizeBytes = 0;
+
+ // Include raw APKs, and possibly unpacked resources
+ for (String codePath : pkg.getAllCodePaths()) {
+ final File codeFile = new File(codePath);
+ sizeBytes += codeFile.length();
+
+ if (isForwardLocked) {
+ sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
+ }
+ }
+
+ // Include all relevant native code
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+
+ return sizeBytes;
+ }
+
public static String replaceEnd(String str, String before, String after) {
if (!str.endsWith(before)) {
throw new IllegalArgumentException(
diff --git a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
index 7ad35d0..06c495e 100644
--- a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import com.android.internal.content.PackageHelper;
+import static android.net.TrafficStats.MB_IN_BYTES;
import android.os.IBinder;
import android.os.RemoteException;
@@ -25,6 +25,8 @@ import android.os.storage.IMountService;
import android.test.AndroidTestCase;
import android.util.Log;
+import com.android.internal.content.PackageHelper;
+
public class PackageHelperTests extends AndroidTestCase {
private static final boolean localLOGV = true;
public static final String TAG = "PackageHelperTests";
@@ -81,8 +83,8 @@ public class PackageHelperTests extends AndroidTestCase {
public void testMountAndPullSdCard() {
try {
fullId = PREFIX;
- fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid(),
- true);
+ fullId2 = PackageHelper.createSdDir(1024 * MB_IN_BYTES, fullId, "none",
+ android.os.Process.myUid(), true);
Log.d(TAG,PackageHelper.getSdDir(fullId));
PackageHelper.unMountSdDir(fullId);
diff --git a/core/tests/coretests/src/android/os/storage/AsecTests.java b/core/tests/coretests/src/android/os/storage/AsecTests.java
index abb8eae..4f724fe 100644
--- a/core/tests/coretests/src/android/os/storage/AsecTests.java
+++ b/core/tests/coretests/src/android/os/storage/AsecTests.java
@@ -90,7 +90,7 @@ public class AsecTests extends AndroidTestCase {
String fullId = SECURE_CONTAINER_PREFIX + localId;
IMountService ms = getMs();
- return ms.mountSecureContainer(fullId, key, android.os.Process.myUid());
+ return ms.mountSecureContainer(fullId, key, android.os.Process.myUid(), true);
}
private int renameContainer(String localId1, String localId2) throws Exception {
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 5701678..621de18 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -295,6 +295,8 @@ public:
data.writeString16(id);
data.writeString16(key);
data.writeInt32(ownerUid);
+ // Assume read-only
+ data.writeInt32(1);
if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) {
ALOGD("mountSecureContainer couldn't call remote");
return -1;
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index fae30e5..1f28324 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -16,7 +16,7 @@
package com.android.defcontainer;
-import static android.net.TrafficStats.MB_IN_BYTES;
+import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import android.app.IntentService;
import android.content.Context;
@@ -67,8 +67,6 @@ import java.io.OutputStream;
public class DefaultContainerService extends IntentService {
private static final String TAG = "DefContainer";
- private static final String LIB_DIR_NAME = "lib";
-
// TODO: migrate native code unpacking to always be a derivative work
private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
@@ -168,7 +166,7 @@ public class DefaultContainerService extends IntentService {
final long sizeBytes;
try {
pkg = PackageParser.parsePackageLite(packageFile, 0);
- sizeBytes = calculateInstalledSizeInner(pkg, isForwardLocked, abiOverride);
+ sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride);
} catch (PackageParserException | IOException e) {
Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e);
@@ -253,7 +251,7 @@ public class DefaultContainerService extends IntentService {
final PackageParser.PackageLite pkg;
try {
pkg = PackageParser.parsePackageLite(packageFile, 0);
- return calculateInstalledSizeInner(pkg, isForwardLocked, abiOverride);
+ return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride);
} catch (PackageParserException | IOException e) {
Slog.w(TAG, "Failed to calculate installed size: " + e);
return Long.MAX_VALUE;
@@ -315,13 +313,12 @@ public class DefaultContainerService extends IntentService {
// Calculate container size, rounding up to nearest MB and adding an
// extra MB for filesystem overhead
- final long sizeBytes = calculateInstalledSizeInner(pkg, handle, isForwardLocked,
- abiOverride);
- final int sizeMb = ((int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES)) + 1;
+ final long sizeBytes = PackageHelper.calculateInstalledSize(pkg, handle,
+ isForwardLocked, abiOverride);
// Create new container
- final String newMountPath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
- isExternal);
+ final String newMountPath = PackageHelper.createSdDir(sizeBytes, newCid, key,
+ Process.myUid(), isExternal);
if (newMountPath == null) {
throw new IOException("Failed to create container " + newCid);
}
@@ -339,8 +336,8 @@ public class DefaultContainerService extends IntentService {
// Extract native code
final File libraryRoot = new File(targetDir, LIB_DIR_NAME);
- final int res = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
- abiOverride, pkg.multiArch);
+ final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
+ abiOverride);
if (res != PackageManager.INSTALL_SUCCEEDED) {
throw new IOException("Failed to extract native code, res=" + res);
}
@@ -415,35 +412,4 @@ public class DefaultContainerService extends IntentService {
Os.chmod(targetFile.getAbsolutePath(), 0644);
}
}
-
- private long calculateInstalledSizeInner(PackageLite pkg, boolean isForwardLocked,
- String abiOverride) throws IOException {
- NativeLibraryHelper.Handle handle = null;
- try {
- handle = NativeLibraryHelper.Handle.create(pkg);
- return calculateInstalledSizeInner(pkg, handle, isForwardLocked, abiOverride);
- } finally {
- IoUtils.closeQuietly(handle);
- }
- }
-
- private long calculateInstalledSizeInner(PackageLite pkg, NativeLibraryHelper.Handle handle,
- boolean isForwardLocked, String abiOverride) throws IOException {
- long sizeBytes = 0;
-
- // Include raw APKs, and possibly unpacked resources
- for (String codePath : pkg.getAllCodePaths()) {
- final File codeFile = new File(codePath);
- sizeBytes += codeFile.length();
-
- if (isForwardLocked) {
- sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
- }
- }
-
- // Include all relevant native code
- sizeBytes += NativeLibraryHelper.sumNativeBinaries(handle, abiOverride, pkg.multiArch);
-
- return sizeBytes;
- }
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 50f2ae9..ea24d7c 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -33,7 +33,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.hardware.usb.UsbManager;
-import android.app.admin.DevicePolicyManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
@@ -1761,6 +1760,21 @@ class MountService extends IMountService.Stub
return rc;
}
+ @Override
+ public int resizeSecureContainer(String id, int sizeMb, String key) {
+ validatePermission(android.Manifest.permission.ASEC_CREATE);
+ waitForReady();
+ warnOnNotMounted();
+
+ int rc = StorageResultCode.OperationSucceeded;
+ try {
+ mConnector.execute("asec", "resize", id, sizeMb, new SensitiveArg(key));
+ } catch (NativeDaemonConnectorException e) {
+ rc = StorageResultCode.OperationFailedInternalError;
+ }
+ return rc;
+ }
+
public int finalizeSecureContainer(String id) {
validatePermission(android.Manifest.permission.ASEC_CREATE);
warnOnNotMounted();
@@ -1835,7 +1849,7 @@ class MountService extends IMountService.Stub
return rc;
}
- public int mountSecureContainer(String id, String key, int ownerUid) {
+ public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) {
validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
waitForReady();
warnOnNotMounted();
@@ -1848,7 +1862,8 @@ class MountService extends IMountService.Stub
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid);
+ mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid,
+ readOnly ? "ro" : "rw");
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 5e802de..6f60d24 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -19,7 +19,6 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_ALL_USERS;
import static android.content.pm.PackageManager.INSTALL_FROM_ADB;
import static android.content.pm.PackageManager.INSTALL_REPLACE_EXISTING;
-import static android.net.TrafficStats.MB_IN_BYTES;
import static com.android.internal.util.XmlUtils.readBitmapAttribute;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -48,8 +47,11 @@ import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
import android.content.pm.PackageInstaller;
+import android.content.pm.PackageParser;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -208,7 +210,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- unclaimed.remove(session.internalStageDir);
+ unclaimed.remove(session.stageDir);
}
// Clean up orphaned staging directories
@@ -234,7 +236,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- final String cid = session.externalStageCid;
+ final String cid = session.stageCid;
if (unclaimed.remove(cid)) {
// Claimed by active session, mount it
@@ -304,10 +306,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
Slog.w(TAG, "Abandoning old session first created at "
+ session.createdMillis);
valid = false;
- } else if (session.internalStageDir != null
- && !session.internalStageDir.exists()) {
+ } else if (session.stageDir != null
+ && !session.stageDir.exists()) {
Slog.w(TAG, "Abandoning internal session with missing stage "
- + session.internalStageDir);
+ + session.stageDir);
valid = false;
} else {
valid = true;
@@ -401,12 +403,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
session.installerPackageName);
writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis);
- if (session.internalStageDir != null) {
+ if (session.stageDir != null) {
writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
- session.internalStageDir.getAbsolutePath());
+ session.stageDir.getAbsolutePath());
}
- if (session.externalStageCid != null) {
- writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.externalStageCid);
+ if (session.stageCid != null) {
+ writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid);
}
writeBooleanAttribute(out, ATTR_SEALED, session.isSealed());
@@ -479,6 +481,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
}
+ // TODO: treat INHERIT_EXISTING as install for user
+
// Figure out where we're going to be staging session data
final boolean stageInternal;
@@ -502,22 +506,36 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
Binder.restoreCallingIdentity(ident);
}
} else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- // We always stage inheriting sessions on internal storage first,
- // since we don't want to grow containers until we're sure that
- // everything looks legit.
- stageInternal = true;
- checkInternalStorage(params.sizeBytes);
-
- // If we have a good hunch we'll end up on external storage, verify
- // free space there too.
- final ApplicationInfo info = mPm.getApplicationInfo(params.appPackageName, 0,
+ // Inheriting existing install, so stay on the same storage medium.
+ final ApplicationInfo existingApp = mPm.getApplicationInfo(params.appPackageName, 0,
userId);
- if (info != null && (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
- checkExternalStorage(params.sizeBytes);
+ if (existingApp == null) {
+ throw new IllegalStateException(
+ "Missing existing app " + params.appPackageName);
+ }
- throw new UnsupportedOperationException("TODO: finish fleshing out ASEC support");
+ final long existingSize;
+ try {
+ final PackageLite existingPkg = PackageParser.parsePackageLite(
+ new File(existingApp.getCodePath()), 0);
+ existingSize = PackageHelper.calculateInstalledSize(existingPkg, false,
+ params.abiOverride);
+ } catch (PackageParserException e) {
+ throw new IllegalStateException(
+ "Failed to calculate size of " + params.appPackageName);
}
+ if ((existingApp.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
+ // Internal we can link existing install into place, so we only
+ // need enough space for the new data.
+ checkInternalStorage(params.sizeBytes);
+ stageInternal = true;
+ } else {
+ // External we're going to copy existing install into our
+ // container, so we need footprint of both.
+ checkExternalStorage(params.sizeBytes + existingSize);
+ stageInternal = false;
+ }
} else {
throw new IllegalArgumentException("Invalid install mode: " + params.mode);
}
@@ -641,11 +659,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
final String cid = "smdl" + sessionId + ".tmp";
-
- // Round up to nearest MB, plus another MB for filesystem overhead
- final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
-
- if (PackageHelper.createSdDir(sizeMb, cid, PackageManagerService.getEncryptKey(),
+ if (PackageHelper.createSdDir(sizeBytes, cid, PackageManagerService.getEncryptKey(),
Process.SYSTEM_UID, true) == null) {
throw new IOException("Failed to create ASEC");
}
@@ -857,7 +871,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
final String existing = extras.getString(
PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
if (!TextUtils.isEmpty(existing)) {
- fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, existing);
+ fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
}
}
try {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 38a2016..5264fc4 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
@@ -38,6 +39,7 @@ import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ApkLite;
+import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.Signature;
import android.os.Bundle;
@@ -47,6 +49,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.system.ErrnoException;
@@ -59,18 +62,21 @@ import android.util.MathUtils;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.ArrayUtils;
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;
import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@@ -95,18 +101,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final SessionParams params;
final long createdMillis;
- /** Internal location where staged data is written. */
- final File internalStageDir;
- /** External container where staged data is written. */
- final String externalStageCid;
-
- /**
- * When a {@link SessionParams#MODE_INHERIT_EXISTING} session is installed
- * into an ASEC, this is the container where the stage is combined with the
- * existing install.
- */
- // TODO: persist this cid once we start splicing
- String combinedCid;
+ /** Staging location where client data is written. */
+ final File stageDir;
+ final String stageCid;
/** Note that UID is not persisted; it's always derived at runtime. */
final int installerUid;
@@ -133,29 +130,34 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private String mFinalMessage;
@GuardedBy("mLock")
- private File mResolvedStageDir;
+ private ArrayList<FileBridge> mBridges = new ArrayList<>();
+
+ @GuardedBy("mLock")
+ private IPackageInstallObserver2 mRemoteObserver;
+
+ /** Fields derived from commit parsing */
+ private String mPackageName;
+ private int mVersionCode;
+ private Signature[] mSignatures;
/**
- * Path to the resolved base APK for this session, which may point at an APK
- * inside the session (when the session defines the base), or it may point
- * at the existing base APK (when adding splits to an existing app).
+ * Path to the validated base APK for this session, which may point at an
+ * APK inside the session (when the session defines the base), or it may
+ * point at the existing base APK (when adding splits to an existing app).
* <p>
* This is used when confirming permissions, since we can't fully stage the
* session inside an ASEC before confirming with user.
*/
@GuardedBy("mLock")
- private String mResolvedBaseCodePath;
+ private File mResolvedBaseFile;
@GuardedBy("mLock")
- private ArrayList<FileBridge> mBridges = new ArrayList<>();
+ private File mResolvedStageDir;
@GuardedBy("mLock")
- private IPackageInstallObserver2 mRemoteObserver;
-
- /** Fields derived from commit parsing */
- private String mPackageName;
- private int mVersionCode;
- private Signature[] mSignatures;
+ private final List<File> mResolvedStagedFiles = new ArrayList<>();
+ @GuardedBy("mLock")
+ private final List<File> mResolvedInheritedFiles = new ArrayList<>();
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
@@ -168,9 +170,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
try {
commitLocked();
} catch (PackageManagerException e) {
- Slog.e(TAG, "Install failed: " + e);
+ final String completeMsg = ExceptionUtils.getCompleteMessage(e);
+ Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
- dispatchSessionFinished(e.error, e.getMessage(), null);
+ dispatchSessionFinished(e.error, completeMsg, null);
}
return true;
@@ -181,7 +184,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
String installerPackageName, SessionParams params, long createdMillis,
- File internalStageDir, String externalStageCid, boolean sealed) {
+ File stageDir, String stageCid, boolean sealed) {
mCallback = callback;
mContext = context;
mPm = pm;
@@ -192,12 +195,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
this.installerPackageName = installerPackageName;
this.params = params;
this.createdMillis = createdMillis;
- this.internalStageDir = internalStageDir;
- this.externalStageCid = externalStageCid;
+ this.stageDir = stageDir;
+ this.stageCid = stageCid;
- if ((internalStageDir == null) == (externalStageCid == null)) {
+ if ((stageDir == null) == (stageCid == null)) {
throw new IllegalArgumentException(
- "Exactly one of internal or external stage must be set");
+ "Exactly one of stageDir or stageCid stage must be set");
}
mSealed = sealed;
@@ -220,7 +223,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
synchronized (mLock) {
info.sessionId = sessionId;
info.installerPackageName = installerPackageName;
- info.resolvedBaseCodePath = mResolvedBaseCodePath;
+ info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
+ mResolvedBaseFile.getAbsolutePath() : null;
info.progress = mProgress;
info.sealed = mSealed;
info.open = mOpenCount.get() > 0;
@@ -253,18 +257,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
* might point at an ASEC mount point, which is why we delay path resolution
* until someone actively works with the session.
*/
- private File getStageDir() throws IOException {
+ private File resolveStageDir() throws IOException {
synchronized (mLock) {
if (mResolvedStageDir == null) {
- if (internalStageDir != null) {
- mResolvedStageDir = internalStageDir;
+ if (stageDir != null) {
+ mResolvedStageDir = stageDir;
} else {
- final String path = PackageHelper.getSdDir(externalStageCid);
+ final String path = PackageHelper.getSdDir(stageCid);
if (path != null) {
mResolvedStageDir = new File(path);
} else {
- throw new IOException(
- "Failed to resolve container path for " + externalStageCid);
+ throw new IOException("Failed to resolve path to container " + stageCid);
}
}
}
@@ -306,7 +309,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public String[] getNames() {
assertNotSealed("getNames");
try {
- return getStageDir().list();
+ return resolveStageDir().list();
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
@@ -339,8 +342,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (!FileUtils.isValidExtFilename(name)) {
throw new IllegalArgumentException("Invalid name: " + name);
}
- final File target = new File(getStageDir(), name);
+ final File target = new File(resolveStageDir(), name);
+ // TODO: this should delegate to DCS so the system process avoids
+ // holding open FDs into containers.
final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(),
O_CREAT | O_WRONLY, 0644);
Os.chmod(target.getAbsolutePath(), 0644);
@@ -350,7 +355,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (lengthBytes > 0) {
final StructStat stat = Libcore.os.fstat(targetFd);
final long deltaBytes = lengthBytes - stat.st_size;
- if (deltaBytes > 0) {
+ // Only need to free up space when writing to internal stage
+ if (stageDir != null && deltaBytes > 0) {
mPm.freeStorage(deltaBytes);
}
Libcore.os.posix_fallocate(targetFd, 0, lengthBytes);
@@ -385,7 +391,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (!FileUtils.isValidExtFilename(name)) {
throw new IllegalArgumentException("Invalid name: " + name);
}
- final File target = new File(getStageDir(), name);
+ final File target = new File(resolveStageDir(), name);
final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_RDONLY, 0);
return new ParcelFileDescriptor(targetFd);
@@ -424,22 +430,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mCallback.onSessionSealed(this);
}
- final File stageDir;
try {
- stageDir = getStageDir();
+ resolveStageDir();
} catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
- "Failed to resolve stage dir", e);
+ "Failed to resolve stage location", e);
}
// Verify that stage looks sane with respect to existing application.
// This currently only ensures packageName, versionCode, and certificate
// consistency.
- validateInstallLocked(stageDir);
+ validateInstallLocked();
Preconditions.checkNotNull(mPackageName);
Preconditions.checkNotNull(mSignatures);
- Preconditions.checkNotNull(mResolvedBaseCodePath);
+ Preconditions.checkNotNull(mResolvedBaseFile);
if (!mPermissionsAccepted) {
// User needs to accept permissions; give installer an intent they
@@ -454,17 +459,41 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
+ if (stageCid != null) {
+ // Figure out the final installed size and resize the container once
+ // and for all. Internally the parser handles straddling between two
+ // locations when inheriting.
+ final long finalSize = calculateInstalledSize();
+ resizeContainer(stageCid, finalSize);
+ }
+
// Inherit any packages and native libraries from existing install that
// haven't been overridden.
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- // TODO: implement splicing into existing ASEC
- spliceExistingFilesIntoStage(stageDir);
+ try {
+ if (stageCid != null) {
+ // TODO: this should delegate to DCS so the system process
+ // avoids holding open FDs into containers.
+ copyFiles(mResolvedInheritedFiles, resolveStageDir());
+ } else {
+ linkFiles(mResolvedInheritedFiles, resolveStageDir());
+ }
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+ "Failed to inherit existing install", e);
+ }
}
// TODO: surface more granular state from dexopt
mCallback.onSessionProgressChanged(this, 0.9f);
- // TODO: for ASEC based applications, grow and stream in packages
+ // Unpack native libraries
+ extractNativeLibraries(mResolvedStageDir, params.abiOverride);
+
+ // Container is ready to go, let's seal it up!
+ if (stageCid != null) {
+ finalizeAndFixContainer(stageCid);
+ }
// We've reached point of no return; call into PMS to install the stage.
// Regardless of success or failure we always destroy session.
@@ -482,7 +511,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
};
- mPm.installStage(mPackageName, this.internalStageDir, this.externalStageCid, localObserver,
+ mPm.installStage(mPackageName, stageDir, stageCid, localObserver,
params, installerPackageName, installerUid, new UserHandle(userId));
}
@@ -490,81 +519,88 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
* Validate install by confirming that all application packages are have
* consistent package name, version code, and signing certificates.
* <p>
+ * Clears and populates {@link #mResolvedBaseFile},
+ * {@link #mResolvedStagedFiles}, and {@link #mResolvedInheritedFiles}.
+ * <p>
* Renames package files in stage to match split names defined inside.
* <p>
* Note that upgrade compatibility is still performed by
* {@link PackageManagerService}.
*/
- private void validateInstallLocked(File stageDir) throws PackageManagerException {
+ private void validateInstallLocked() throws PackageManagerException {
mPackageName = null;
mVersionCode = -1;
mSignatures = null;
- mResolvedBaseCodePath = null;
- final File[] files = stageDir.listFiles();
+ mResolvedBaseFile = null;
+ mResolvedStagedFiles.clear();
+ mResolvedInheritedFiles.clear();
+
+ final File[] files = mResolvedStageDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
}
// Verify that all staged packages are internally consistent
- final ArraySet<String> seenSplits = new ArraySet<>();
+ final ArraySet<String> stagedSplits = new ArraySet<>();
for (File file : files) {
// Installers can't stage directories, so it's fine to ignore
// entries like "lost+found".
if (file.isDirectory()) continue;
- final ApkLite info;
+ final ApkLite apk;
try {
- info = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
+ apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Failed to parse " + file + ": " + e);
}
- if (!seenSplits.add(info.splitName)) {
+ if (!stagedSplits.add(apk.splitName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Split " + info.splitName + " was defined multiple times");
+ "Split " + apk.splitName + " was defined multiple times");
}
// Use first package to define unknown values
if (mPackageName == null) {
- mPackageName = info.packageName;
- mVersionCode = info.versionCode;
+ mPackageName = apk.packageName;
+ mVersionCode = apk.versionCode;
}
if (mSignatures == null) {
- mSignatures = info.signatures;
+ mSignatures = apk.signatures;
}
- assertPackageConsistent(String.valueOf(file), info.packageName, info.versionCode,
- info.signatures);
+ assertApkConsistent(String.valueOf(file), apk);
// Take this opportunity to enforce uniform naming
final String targetName;
- if (info.splitName == null) {
+ if (apk.splitName == null) {
targetName = "base.apk";
} else {
- targetName = "split_" + info.splitName + ".apk";
+ targetName = "split_" + apk.splitName + ".apk";
}
if (!FileUtils.isValidExtFilename(targetName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Invalid filename: " + targetName);
}
- final File targetFile = new File(stageDir, targetName);
+ final File targetFile = new File(mResolvedStageDir, targetName);
if (!file.equals(targetFile)) {
file.renameTo(targetFile);
}
// Base is coming from session
- if (info.splitName == null) {
- mResolvedBaseCodePath = targetFile.getAbsolutePath();
+ if (apk.splitName == null) {
+ mResolvedBaseFile = targetFile;
}
+
+ mResolvedStagedFiles.add(targetFile);
}
if (params.mode == SessionParams.MODE_FULL_INSTALL) {
// Full installs must include a base package
- if (!seenSplits.contains(null)) {
+ if (!stagedSplits.contains(null)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Full install must include a base package");
}
@@ -577,67 +613,204 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
"Missing existing base package for " + mPackageName);
}
- // Base might be inherited from existing install
- if (mResolvedBaseCodePath == null) {
- mResolvedBaseCodePath = app.getBaseCodePath();
- }
-
- final ApkLite info;
+ final PackageLite existing;
+ final ApkLite existingBase;
try {
- info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
+ existing = PackageParser.parsePackageLite(new File(app.getCodePath()), 0);
+ existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse existing base " + app.getBaseCodePath() + ": " + e);
+ "Failed to parse existing package " + app.getCodePath() + ": " + e);
+ }
+
+ assertApkConsistent("Existing base", existingBase);
+
+ // Inherit base if not overridden
+ if (mResolvedBaseFile == null) {
+ mResolvedBaseFile = new File(app.getBaseCodePath());
+ mResolvedInheritedFiles.add(mResolvedBaseFile);
}
- assertPackageConsistent("Existing base", info.packageName, info.versionCode,
- info.signatures);
+ // Inherit splits if not overridden
+ if (!ArrayUtils.isEmpty(existing.splitNames)) {
+ for (int i = 0; i < existing.splitNames.length; i++) {
+ final String splitName = existing.splitNames[i];
+ final File splitFile = new File(existing.splitCodePaths[i]);
+
+ if (!stagedSplits.contains(splitName)) {
+ mResolvedInheritedFiles.add(splitFile);
+ }
+ }
+ }
}
}
- private void assertPackageConsistent(String tag, String packageName, int versionCode,
- Signature[] signatures) throws PackageManagerException {
- if (!mPackageName.equals(packageName)) {
+ private void assertApkConsistent(String tag, ApkLite apk) throws PackageManagerException {
+ if (!mPackageName.equals(apk.packageName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
- + packageName + " inconsistent with " + mPackageName);
+ + apk.packageName + " inconsistent with " + mPackageName);
}
- if (mVersionCode != versionCode) {
+ if (mVersionCode != apk.versionCode) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
- + " version code " + versionCode + " inconsistent with "
+ + " version code " + apk.versionCode + " inconsistent with "
+ mVersionCode);
}
- if (!Signature.areExactMatch(mSignatures, signatures)) {
+ if (!Signature.areExactMatch(mSignatures, apk.signatures)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
tag + " signatures are inconsistent");
}
}
/**
- * Application is already installed; splice existing files that haven't been
- * overridden into our stage.
+ * Calculate the final install footprint size, combining both staged and
+ * existing APKs together and including unpacked native code from both.
*/
- private void spliceExistingFilesIntoStage(File stageDir) throws PackageManagerException {
- final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
+ private long calculateInstalledSize() throws PackageManagerException {
+ Preconditions.checkNotNull(mResolvedBaseFile);
- int n = 0;
- final File[] oldFiles = new File(app.getCodePath()).listFiles();
- if (!ArrayUtils.isEmpty(oldFiles)) {
- for (File oldFile : oldFiles) {
- if (!PackageParser.isApkFile(oldFile)) continue;
+ final ApkLite baseApk;
+ try {
+ baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0);
+ } catch (PackageParserException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+ "Failed to parse base package " + mResolvedBaseFile + ": " + e);
+ }
- final File newFile = new File(stageDir, oldFile.getName());
- try {
- Os.link(oldFile.getAbsolutePath(), newFile.getAbsolutePath());
- n++;
- } catch (ErrnoException e) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Failed to splice into stage", e);
- }
+ final List<String> splitPaths = new ArrayList<>();
+ for (File file : mResolvedStagedFiles) {
+ if (mResolvedBaseFile.equals(file)) continue;
+ splitPaths.add(file.getAbsolutePath());
+ }
+ for (File file : mResolvedInheritedFiles) {
+ if (mResolvedBaseFile.equals(file)) continue;
+ splitPaths.add(file.getAbsolutePath());
+ }
+
+ // This is kind of hacky; we're creating a half-parsed package that is
+ // straddled between the inherited and staged APKs.
+ final PackageLite pkg = new PackageLite(null, baseApk, null,
+ splitPaths.toArray(new String[splitPaths.size()]));
+ final boolean isForwardLocked =
+ (params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+
+ try {
+ return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, params.abiOverride);
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+ "Failed to calculate install size", e);
+ }
+ }
+
+ private static void linkFiles(List<File> fromFiles, File toDir) throws IOException {
+ for (File fromFile : fromFiles) {
+ final File toFile = new File(toDir, fromFile.getName());
+ try {
+ if (LOGD) Slog.d(TAG, "Linking " + fromFile + " to " + toFile);
+ Os.link(fromFile.getAbsolutePath(), toFile.getAbsolutePath());
+ } catch (ErrnoException e) {
+ throw new IOException("Failed to link " + fromFile + " to " + toFile, e);
+ }
+ }
+ Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir);
+ }
+
+ private static void copyFiles(List<File> fromFiles, File toDir) throws IOException {
+ // Remove any partial files from previous attempt
+ for (File file : toDir.listFiles()) {
+ if (file.getName().endsWith(".tmp")) {
+ file.delete();
+ }
+ }
+
+ for (File fromFile : fromFiles) {
+ final File tmpFile = File.createTempFile("inherit", ".tmp", toDir);
+ if (LOGD) Slog.d(TAG, "Copying " + fromFile + " to " + tmpFile);
+ if (!FileUtils.copyFile(fromFile, tmpFile)) {
+ throw new IOException("Failed to copy " + fromFile + " to " + tmpFile);
+ }
+
+ final File toFile = new File(toDir, fromFile.getName());
+ if (LOGD) Slog.d(TAG, "Renaming " + tmpFile + " to " + toFile);
+ if (!tmpFile.renameTo(toFile)) {
+ throw new IOException("Failed to rename " + tmpFile + " to " + toFile);
+ }
+ }
+ Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir);
+ }
+
+ private static void extractNativeLibraries(File packageDir, String abiOverride)
+ throws PackageManagerException {
+ if (LOGD) Slog.v(TAG, "extractNativeLibraries()");
+
+ // Always start from a clean slate
+ final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
+ NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+
+ NativeLibraryHelper.Handle handle = null;
+ try {
+ handle = NativeLibraryHelper.Handle.create(packageDir);
+ final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libDir,
+ abiOverride);
+ if (res != PackageManager.INSTALL_SUCCEEDED) {
+ throw new PackageManagerException(res,
+ "Failed to extract native libraries, res=" + res);
}
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Failed to extract native libraries", e);
+ } finally {
+ IoUtils.closeQuietly(handle);
+ }
+ }
+
+ private static void resizeContainer(String cid, long targetSize)
+ throws PackageManagerException {
+ String path = PackageHelper.getSdDir(cid);
+ if (path == null) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to find mounted " + cid);
+ }
+
+ final long currentSize = new File(path).getTotalSpace();
+ if (currentSize > targetSize) {
+ Slog.w(TAG, "Current size " + currentSize + " is larger than target size "
+ + targetSize + "; skipping resize");
+ return;
+ }
+
+ if (!PackageHelper.unMountSdDir(cid)) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to unmount " + cid + " before resize");
}
- if (LOGD) Slog.d(TAG, "Spliced " + n + " existing APKs into stage");
+ if (!PackageHelper.resizeSdDir(targetSize, cid,
+ PackageManagerService.getEncryptKey())) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to resize " + cid + " to " + targetSize + " bytes");
+ }
+
+ path = PackageHelper.mountSdDir(cid, PackageManagerService.getEncryptKey(),
+ Process.SYSTEM_UID, false);
+ if (path == null) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to mount " + cid + " after resize");
+ }
+ }
+
+ private void finalizeAndFixContainer(String cid) throws PackageManagerException {
+ if (!PackageHelper.finalizeSdDir(cid)) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to finalize container " + cid);
+ }
+
+ final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
+ UserHandle.USER_OWNER);
+ final int gid = UserHandle.getSharedAppGid(uid);
+ if (!PackageHelper.fixSdPermissions(cid, gid, null)) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to fix permissions on container " + cid);
+ }
}
void setPermissionsResult(boolean accepted) {
@@ -694,12 +867,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mSealed = true;
mDestroyed = true;
}
- if (internalStageDir != null) {
- FileUtils.deleteContents(internalStageDir);
- internalStageDir.delete();
+ if (stageDir != null) {
+ FileUtils.deleteContents(stageDir);
+ stageDir.delete();
}
- if (externalStageCid != null) {
- PackageHelper.destroySdDir(externalStageCid);
+ if (stageCid != null) {
+ PackageHelper.destroySdDir(stageCid);
}
}
@@ -717,8 +890,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
pw.printPair("installerPackageName", installerPackageName);
pw.printPair("installerUid", installerUid);
pw.printPair("createdMillis", createdMillis);
- pw.printPair("internalStageDir", internalStageDir);
- pw.printPair("externalStageCid", externalStageCid);
+ pw.printPair("stageDir", stageDir);
+ pw.printPair("stageCid", stageCid);
pw.println();
params.dump(pw);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index aa49b27..f06992a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -50,6 +50,8 @@ import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
+import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
+import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
@@ -298,9 +300,6 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
- private static final String LIB_DIR_NAME = "lib";
- private static final String LIB64_DIR_NAME = "lib64";
-
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
private static String sPreferredInstructionSet;
@@ -1121,7 +1120,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if ((state != null) && !state.timeoutExtended()) {
final InstallArgs args = state.getInstallArgs();
- final Uri originUri = Uri.fromFile(args.originFile);
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
mPendingVerification.remove(verificationId);
@@ -1168,7 +1167,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mPendingVerification.remove(verificationId);
final InstallArgs args = state.getInstallArgs();
- final Uri originUri = Uri.fromFile(args.originFile);
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
int ret;
if (state.isInstallAllowed()) {
@@ -4271,7 +4270,7 @@ public class PackageManagerService extends IPackageManager.Stub {
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
- getAppDexInstructionSets(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -4334,7 +4333,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
- getAppDexInstructionSets(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -5527,8 +5526,9 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isAsec) {
abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
} else {
- abi32 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, useIsaSpecificSubdirs);
+ abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
+ useIsaSpecificSubdirs);
}
}
@@ -5539,8 +5539,9 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isAsec) {
abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
} else {
- abi64 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, useIsaSpecificSubdirs);
+ abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
+ useIsaSpecificSubdirs);
}
}
@@ -5578,7 +5579,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isAsec) {
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
} else {
- copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+ copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
}
@@ -7782,7 +7783,8 @@ public class PackageManagerService extends IPackageManager.Stub {
verificationParams.setInstallerUid(uid);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(originFile, null, false, observer, filteredFlags,
+ final OriginInfo origin = new OriginInfo(originFile, null, false);
+ msg.obj = new InstallParams(origin, observer, filteredFlags,
installerPackageName, verificationParams, user, packageAbiOverride);
mHandler.sendMessage(msg);
}
@@ -7794,7 +7796,8 @@ public class PackageManagerService extends IPackageManager.Stub {
params.referrerUri, installerUid, null);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(stagedDir, stagedCid, true, observer, params.installFlags,
+ final OriginInfo origin = new OriginInfo(stagedDir, stagedCid, true);
+ msg.obj = new InstallParams(origin, observer, params.installFlags,
installerPackageName, verifParams, user, params.abiOverride);
mHandler.sendMessage(msg);
}
@@ -8487,22 +8490,45 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- class InstallParams extends HandlerParams {
+ static class OriginInfo {
/**
* Location where install is coming from, before it has been
* copied/renamed into place. This could be a single monolithic APK
* file, or a cluster directory. This location may be untrusted.
*/
- final File originFile;
- final String originCid;
+ final File file;
+ final String cid;
/**
- * Flag indicating that {@link #originFile} or {@link #originCid} has
- * already been staged, meaning downstream users don't need to
- * defensively copy the contents.
+ * Flag indicating that {@link #file} or {@link #cid} has already been
+ * staged, meaning downstream users don't need to defensively copy the
+ * contents.
*/
- boolean originStaged;
+ final boolean staged;
+
+ final String resolvedPath;
+ final File resolvedFile;
+
+ public OriginInfo(File file, String cid, boolean staged) {
+ this.file = file;
+ this.cid = cid;
+ this.staged = staged;
+
+ if (cid != null) {
+ resolvedPath = PackageHelper.getSdDir(cid);
+ resolvedFile = new File(resolvedPath);
+ } else if (file != null) {
+ resolvedPath = file.getAbsolutePath();
+ resolvedFile = file;
+ } else {
+ resolvedPath = null;
+ resolvedFile = null;
+ }
+ }
+ }
+ class InstallParams extends HandlerParams {
+ final OriginInfo origin;
final IPackageInstallObserver2 observer;
int flags;
final String installerPackageName;
@@ -8510,15 +8536,12 @@ public class PackageManagerService extends IPackageManager.Stub {
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
- boolean multiArch;
- InstallParams(File originFile, String originCid, boolean originStaged,
- IPackageInstallObserver2 observer, int flags, String installerPackageName,
- VerificationParams verificationParams, UserHandle user, String packageAbiOverride) {
+ InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int flags,
+ String installerPackageName, VerificationParams verificationParams, UserHandle user,
+ String packageAbiOverride) {
super(user);
- this.originFile = originFile;
- this.originCid = originCid;
- this.originStaged = originStaged;
+ this.origin = origin;
this.observer = observer;
this.flags = flags;
this.installerPackageName = installerPackageName;
@@ -8529,7 +8552,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public String toString() {
return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
- + " file=" + originFile + " cid=" + originCid + "}";
+ + " file=" + origin.file + " cid=" + origin.cid + "}";
}
public ManifestDigest getManifestDigest() {
@@ -8608,11 +8631,11 @@ public class PackageManagerService extends IPackageManager.Stub {
int ret = PackageManager.INSTALL_SUCCEEDED;
// If we're already staged, we've firmly committed to an install location
- if (originStaged) {
- if (originFile != null) {
+ if (origin.staged) {
+ if (origin.file != null) {
flags |= PackageManager.INSTALL_INTERNAL;
flags &= ~PackageManager.INSTALL_EXTERNAL;
- } else if (originCid != null) {
+ } else if (origin.cid != null) {
flags |= PackageManager.INSTALL_EXTERNAL;
flags &= ~PackageManager.INSTALL_INTERNAL;
} else {
@@ -8622,6 +8645,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
@@ -8629,21 +8653,14 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
- // Remote call to find out default install location
- final String originPath = originFile.getAbsolutePath();
- pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags,
+ pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, flags,
packageAbiOverride);
- // Keep track of whether this package is a multiArch package until
- // we perform a full scan of it. We need to do this because we might
- // end up extracting the package shared libraries before we perform
- // a full scan.
- multiArch = pkgLite.multiArch;
/*
* If we have too little free space, try to free cache
* before giving up.
*/
- if (!originStaged && pkgLite.recommendedInstallLocation
+ if (!origin.staged && pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
// TODO: focus freeing disk space on the target device
final StorageManager storage = StorageManager.from(mContext);
@@ -8651,11 +8668,11 @@ public class PackageManagerService extends IPackageManager.Stub {
Environment.getDataDirectory());
final long sizeBytes = mContainerService.calculateInstalledSize(
- originPath, isForwardLocked(), packageAbiOverride);
+ origin.resolvedPath, isForwardLocked(), packageAbiOverride);
if (mInstaller.freeCache(sizeBytes + lowThreshold) >= 0) {
- pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags,
- packageAbiOverride);
+ pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
+ flags, packageAbiOverride);
}
/*
@@ -8729,10 +8746,10 @@ public class PackageManagerService extends IPackageManager.Stub {
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, userIdentifier);
if (requiredUid != -1 && isVerificationEnabled(userIdentifier, flags)) {
- // TODO: send verifier the install session instead of uri
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.setDataAndType(Uri.fromFile(originFile), PACKAGE_MIME_TYPE);
+ verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification,
@@ -8890,8 +8907,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int mRet;
MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
- String packageName, String[] instructionSets, int uid, UserHandle user,
- boolean isMultiArch) {
+ String packageName, String[] instructionSets, int uid, UserHandle user) {
super(user);
this.srcArgs = srcArgs;
this.observer = observer;
@@ -8901,7 +8917,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (srcArgs != null) {
final String codePath = srcArgs.getCodePath();
targetArgs = createInstallArgsForMoveTarget(codePath, flags, packageName,
- instructionSets, isMultiArch);
+ instructionSets);
} else {
targetArgs = null;
}
@@ -9002,8 +9018,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private InstallArgs createInstallArgs(InstallParams params) {
- // TODO: extend to support incoming zero-copy locations
-
if (installOnSd(params.flags) || params.isForwardLocked()) {
return new AsecInstallArgs(params);
} else {
@@ -9016,8 +9030,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* when cleaning up old installs, or used as a move source.
*/
private InstallArgs createInstallArgsForExisting(int flags, String codePath,
- String resourcePath, String nativeLibraryRoot, String[] instructionSets,
- boolean isMultiArch) {
+ String resourcePath, String nativeLibraryRoot, String[] instructionSets) {
final boolean isInAsec;
if (installOnSd(flags)) {
/* Apps on SD card are always in ASEC containers. */
@@ -9035,33 +9048,29 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isInAsec) {
return new AsecInstallArgs(codePath, instructionSets,
- installOnSd(flags), installForwardLocked(flags), isMultiArch);
+ installOnSd(flags), installForwardLocked(flags));
} else {
return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
- instructionSets, isMultiArch);
+ instructionSets);
}
}
private InstallArgs createInstallArgsForMoveTarget(String codePath, int flags, String pkgName,
- String[] instructionSets, boolean isMultiArch) {
+ String[] instructionSets) {
final File codeFile = new File(codePath);
if (installOnSd(flags) || installForwardLocked(flags)) {
String cid = getNextCodePath(codePath, pkgName, "/"
+ AsecInstallArgs.RES_FILE_NAME);
return new AsecInstallArgs(codeFile, cid, instructionSets, installOnSd(flags),
- installForwardLocked(flags), isMultiArch);
+ installForwardLocked(flags));
} else {
- return new FileInstallArgs(codeFile, instructionSets, isMultiArch);
+ return new FileInstallArgs(codeFile, instructionSets);
}
}
static abstract class InstallArgs {
- /** @see InstallParams#originFile */
- final File originFile;
- /** @see InstallParams#originStaged */
- final boolean originStaged;
-
- // TODO: define inherit location
+ /** @see InstallParams#origin */
+ final OriginInfo origin;
final IPackageInstallObserver2 observer;
// Always refers to PackageManager flags only
@@ -9070,19 +9079,16 @@ public class PackageManagerService extends IPackageManager.Stub {
final ManifestDigest manifestDigest;
final UserHandle user;
final String abiOverride;
- final boolean multiArch;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
// if we move dex files under the common app path.
/* nullable */ String[] instructionSets;
- InstallArgs(File originFile, boolean originStaged, IPackageInstallObserver2 observer,
- int flags, String installerPackageName, ManifestDigest manifestDigest,
- UserHandle user, String[] instructionSets,
- String abiOverride, boolean multiArch) {
- this.originFile = originFile;
- this.originStaged = originStaged;
+ InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int flags,
+ String installerPackageName, ManifestDigest manifestDigest, UserHandle user,
+ String[] instructionSets, String abiOverride) {
+ this.origin = origin;
this.flags = flags;
this.observer = observer;
this.installerPackageName = installerPackageName;
@@ -9090,7 +9096,6 @@ public class PackageManagerService extends IPackageManager.Stub {
this.user = user;
this.instructionSets = instructionSets;
this.abiOverride = abiOverride;
- this.multiArch = multiArch;
}
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -9161,10 +9166,9 @@ public class PackageManagerService extends IPackageManager.Stub {
/** New install */
FileInstallArgs(InstallParams params) {
- super(params.originFile, params.originStaged, params.observer, params.flags,
+ super(params.origin, params.observer, params.flags,
params.installerPackageName, params.getManifestDigest(), params.getUser(),
- null /* instruction sets */, params.packageAbiOverride,
- params.multiArch);
+ null /* instruction sets */, params.packageAbiOverride);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -9172,8 +9176,8 @@ public class PackageManagerService extends IPackageManager.Stub {
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath,
- String[] instructionSets, boolean isMultiArch) {
- super(null, false, null, 0, null, null, null, instructionSets, null, isMultiArch);
+ String[] instructionSets) {
+ super(new OriginInfo(null, null, false), null, 0, 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) ?
@@ -9181,13 +9185,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
/** New install from existing */
- FileInstallArgs(File originFile, String[] instructionSets, boolean isMultiArch) {
- super(originFile, false, null, 0, null, null, null, instructionSets, null,
- isMultiArch);
+ FileInstallArgs(File originFile, String[] instructionSets) {
+ super(new OriginInfo(originFile, null, false), null, 0, null, null, null, instructionSets, null);
}
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
- final long sizeBytes = imcs.calculateInstalledSize(originFile.getAbsolutePath(),
+ final long sizeBytes = imcs.calculateInstalledSize(origin.file.getAbsolutePath(),
isFwdLocked(), abiOverride);
final StorageManager storage = StorageManager.from(mContext);
@@ -9195,53 +9198,53 @@ public class PackageManagerService extends IPackageManager.Stub {
}
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
- int ret = PackageManager.INSTALL_SUCCEEDED;
+ if (origin.staged) {
+ Slog.d(TAG, origin.file + " already staged; skipping copy");
+ codeFile = origin.file;
+ resourceFile = origin.file;
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
- if (originStaged) {
- Slog.d(TAG, originFile + " already staged; skipping copy");
- codeFile = originFile;
- resourceFile = originFile;
- } else {
- try {
- final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
- codeFile = tempDir;
- resourceFile = tempDir;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to create copy file: " + e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
+ try {
+ final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
+ codeFile = tempDir;
+ resourceFile = tempDir;
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to create copy file: " + e);
+ return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
- final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
- @Override
- public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
- if (!FileUtils.isValidExtFilename(name)) {
- throw new IllegalArgumentException("Invalid filename: " + name);
- }
- try {
- final File file = new File(codeFile, name);
- final FileDescriptor fd = Os.open(file.getAbsolutePath(),
- O_RDWR | O_CREAT, 0644);
- Os.chmod(file.getAbsolutePath(), 0644);
- return new ParcelFileDescriptor(fd);
- } catch (ErrnoException e) {
- throw new RemoteException("Failed to open: " + e.getMessage());
- }
+ final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
+ @Override
+ public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
+ if (!FileUtils.isValidExtFilename(name)) {
+ throw new IllegalArgumentException("Invalid filename: " + name);
+ }
+ try {
+ final File file = new File(codeFile, name);
+ final FileDescriptor fd = Os.open(file.getAbsolutePath(),
+ O_RDWR | O_CREAT, 0644);
+ Os.chmod(file.getAbsolutePath(), 0644);
+ return new ParcelFileDescriptor(fd);
+ } catch (ErrnoException e) {
+ throw new RemoteException("Failed to open: " + e.getMessage());
}
- };
-
- ret = imcs.copyPackage(originFile.getAbsolutePath(), target);
- if (ret != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Failed to copy package");
- return ret;
}
+ };
+
+ int ret = PackageManager.INSTALL_SUCCEEDED;
+ ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
+ if (ret != PackageManager.INSTALL_SUCCEEDED) {
+ Slog.e(TAG, "Failed to copy package");
+ return ret;
}
final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
- ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
- abiOverride, multiArch);
+ ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
+ abiOverride);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -9429,18 +9432,18 @@ public class PackageManagerService extends IPackageManager.Stub {
/** New install */
AsecInstallArgs(InstallParams params) {
- super(params.originFile, params.originStaged, params.observer, params.flags,
+ super(params.origin, params.observer, params.flags,
params.installerPackageName, params.getManifestDigest(),
params.getUser(), null /* instruction sets */,
- params.packageAbiOverride, params.multiArch);
+ params.packageAbiOverride);
}
/** Existing install */
AsecInstallArgs(String fullCodePath, String[] instructionSets,
- boolean isExternal, boolean isForwardLocked, boolean isMultiArch) {
- super(null, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
+ boolean isExternal, boolean isForwardLocked) {
+ super(new OriginInfo(null, null, false), null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, isMultiArch);
+ instructionSets, null);
// Hackily pretend we're still looking at a full code path
if (!fullCodePath.endsWith(RES_FILE_NAME)) {
fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
@@ -9454,21 +9457,20 @@ public class PackageManagerService extends IPackageManager.Stub {
setMountPath(subStr1);
}
- AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked,
- boolean isMultiArch) {
- super(null, false, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
+ AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
+ super(new OriginInfo(null, null, false), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, isMultiArch);
+ instructionSets, null);
this.cid = cid;
setMountPath(PackageHelper.getSdDir(cid));
}
/** New install from existing */
AsecInstallArgs(File originPackageFile, String cid, String[] instructionSets,
- boolean isExternal, boolean isForwardLocked, boolean isMultiArch) {
- super(originPackageFile, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
+ boolean isExternal, boolean isForwardLocked) {
+ super(new OriginInfo(originPackageFile, null, false), null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, isMultiArch);
+ instructionSets, null);
this.cid = cid;
}
@@ -9496,7 +9498,13 @@ public class PackageManagerService extends IPackageManager.Stub {
}
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
- // TODO: if already staged, we only need to extract native code
+ if (origin.staged) {
+ Slog.d(TAG, origin.cid + " already staged; skipping copy");
+ cid = origin.cid;
+ setMountPath(PackageHelper.getSdDir(cid));
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
if (temp) {
createCopyFile();
} else {
@@ -9508,7 +9516,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final String newMountPath = imcs.copyPackageToContainer(
- originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
+ origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
if (newMountPath != null) {
@@ -10133,8 +10141,7 @@ public class PackageManagerService extends IPackageManager.Stub {
deletedPackage.applicationInfo.getCodePath(),
deletedPackage.applicationInfo.getResourcePath(),
deletedPackage.applicationInfo.nativeLibraryRootDir,
- getAppDexInstructionSets(deletedPackage.applicationInfo),
- isMultiArch(deletedPackage.applicationInfo));
+ getAppDexInstructionSets(deletedPackage.applicationInfo));
} else {
res.removedInfo.args = null;
}
@@ -10920,7 +10927,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
- getAppDexInstructionSets(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
return true;
@@ -12725,7 +12732,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final AsecInstallArgs args = new AsecInstallArgs(cid,
- getAppDexInstructionSets(ps), isForwardLocked(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps), isForwardLocked(ps));
// The package status is changed only if the code path
// matches between settings and the container id.
if (ps.codePathString != null
@@ -13019,7 +13026,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* anyway.
*/
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
- processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user, false),
+ processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user),
returnCode);
} else {
Message msg = mHandler.obtainMessage(INIT_COPY);
@@ -13027,9 +13034,9 @@ public class PackageManagerService extends IPackageManager.Stub {
final boolean multiArch = isMultiArch(pkg.applicationInfo);
InstallArgs srcArgs = createInstallArgsForExisting(currFlags,
pkg.applicationInfo.getCodePath(), pkg.applicationInfo.getResourcePath(),
- pkg.applicationInfo.nativeLibraryRootDir, instructionSets, multiArch);
+ pkg.applicationInfo.nativeLibraryRootDir, instructionSets);
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
- instructionSets, pkg.applicationInfo.uid, user, multiArch);
+ instructionSets, pkg.applicationInfo.uid, user);
msg.obj = mp;
mHandler.sendMessage(msg);
}
@@ -13107,8 +13114,8 @@ public class PackageManagerService extends IPackageManager.Stub {
final int abi = NativeLibraryHelper.findSupportedAbi(
handle, Build.SUPPORTED_ABIS);
if (abi >= 0) {
- NativeLibraryHelper.copyNativeBinariesIfNeededLI(
- handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
+ NativeLibraryHelper.copyNativeBinaries(handle,
+ newNativeDir, Build.SUPPORTED_ABIS[abi]);
}
} catch (IOException ioe) {
Slog.w(TAG, "Unable to extract native libs for package :"