summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Calin Juravle <calin@google.com> 2017-11-29 18:26:55 -0800
committer Calin Juravle <calin@google.com> 2017-12-06 18:29:06 +0000
commitfd9f8ae973122a50f336e38c386ecbc0095d8adc (patch)
treeaf3bab0b76d62a15952f9d2fadddc3c2aed78b3f
parent839edb1781264eb268711075add1e4e31a18caed (diff)
Implement ArtManager#snapshotProfile API
Complete the implementation of ArtManager#snapshotProfile. The snapshot is performed by calling the installer and then return to the caller via the specified callback. Bug: 30934496 Test: gts-tradefed -m GtsAndroidRuntimeManagerHostTestCases Change-Id: I87131487846d91d79a56041445420376b61ca8e7
-rw-r--r--core/java/android/os/Environment.java5
-rw-r--r--services/core/java/com/android/server/pm/Installer.java20
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/dex/ArtManagerService.java84
4 files changed, 105 insertions, 6 deletions
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f977c1dea438..1745121c2b9d 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -291,8 +291,9 @@ public class Environment {
}
/** {@hide} */
- public static File getReferenceProfile(String packageName) {
- return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName);
+ public static File getProfileSnapshotPath(String packageName, String codePath) {
+ return buildPath(buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName,
+ "primary.prof.snapshot"));
}
/** {@hide} */
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 6a06be2fcaa9..2af401f46516 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -496,6 +496,26 @@ public class Installer extends SystemService {
}
}
+ public boolean createProfileSnapshot(int appId, String packageName, String codePath)
+ throws InstallerException {
+ if (!checkBeforeRemote()) return false;
+ try {
+ return mInstalld.snapshotProfile(appId, packageName, codePath);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void destroyProfileSnapshot(String packageName, String codePath)
+ throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyProfileSnapshot(packageName, codePath);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public void invalidateMounts() throws InstallerException {
if (!checkBeforeRemote()) return;
try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4e1ed9d17eb4..8b2854c56977 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3038,7 +3038,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
mInstallerService = new PackageInstallerService(context, this);
- mArtManagerService = new ArtManagerService(this);
+ mArtManagerService = new ArtManagerService(this, mInstaller, mInstallLock);
final Pair<ComponentName, String> instantAppResolverComponent =
getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 5a1f840e945b..2dbb34d888e5 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -21,15 +21,23 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.dex.ArtManager;
import android.os.Binder;
+import android.os.Environment;
import android.os.Handler;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.content.pm.IPackageManager;
import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
+import com.android.server.pm.Installer;
+import com.android.server.pm.Installer.InstallerException;
+import java.io.File;
+import java.io.FileNotFoundException;
/**
* A system service that provides access to runtime and compiler artifacts.
@@ -50,10 +58,16 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
private static boolean DEBUG_IGNORE_PERMISSIONS = false;
private final IPackageManager mPackageManager;
+ private final Object mInstallLock;
+ @GuardedBy("mInstallLock")
+ private final Installer mInstaller;
+
private final Handler mHandler;
- public ArtManagerService(IPackageManager pm) {
+ public ArtManagerService(IPackageManager pm, Installer installer, Object installLock) {
mPackageManager = pm;
+ mInstaller = installer;
+ mInstallLock = installLock;
mHandler = new Handler(BackgroundThread.getHandler().getLooper());
}
@@ -105,8 +119,53 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
return;
}
- // All good, move forward and get the profile.
- postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ // All good, create the profile snapshot.
+ createProfileSnapshot(packageName, codePath, callback, info);
+ // Destroy the snapshot, we no longer need it.
+ destroyProfileSnapshot(packageName, codePath);
+ }
+
+ private void createProfileSnapshot(String packageName, String codePath,
+ ISnapshotRuntimeProfileCallback callback, PackageInfo info) {
+ // Ask the installer to snapshot the profile.
+ synchronized (mInstallLock) {
+ try {
+ if (!mInstaller.createProfileSnapshot(UserHandle.getAppId(info.applicationInfo.uid),
+ packageName, codePath)) {
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ return;
+ }
+ } catch (InstallerException e) {
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ return;
+ }
+ }
+
+ // Open the snapshot and invoke the callback.
+ File snapshotProfile = Environment.getProfileSnapshotPath(packageName, codePath);
+ ParcelFileDescriptor fd;
+ try {
+ fd = ParcelFileDescriptor.open(snapshotProfile, ParcelFileDescriptor.MODE_READ_ONLY);
+ postSuccess(packageName, fd, callback);
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Could not open snapshot profile for " + packageName + ":" + codePath, e);
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ }
+ }
+
+ private void destroyProfileSnapshot(String packageName, String codePath) {
+ if (DEBUG) {
+ Slog.d(TAG, "Destroying profile snapshot for" + packageName + ":" + codePath);
+ }
+
+ synchronized (mInstallLock) {
+ try {
+ mInstaller.destroyProfileSnapshot(packageName, codePath);
+ } catch (InstallerException e) {
+ Slog.e(TAG, "Failed to destroy profile snapshot for " +
+ packageName + ":" + codePath, e);
+ }
+ }
}
@Override
@@ -123,6 +182,10 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
*/
private void postError(ISnapshotRuntimeProfileCallback callback, String packageName,
int errCode) {
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to snapshot profile for " + packageName + " with error: " +
+ errCode);
+ }
mHandler.post(() -> {
try {
callback.onError(errCode);
@@ -132,6 +195,21 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
});
}
+ private void postSuccess(String packageName, ParcelFileDescriptor fd,
+ ISnapshotRuntimeProfileCallback callback) {
+ if (DEBUG) {
+ Slog.d(TAG, "Successfully snapshot profile for " + packageName);
+ }
+ mHandler.post(() -> {
+ try {
+ callback.onSuccess(fd);
+ } catch (RemoteException e) {
+ Slog.w(TAG,
+ "Failed to call onSuccess after profile snapshot for " + packageName, e);
+ }
+ });
+ }
+
/**
* Verify that the binder calling uid has {@code android.permission.READ_RUNTIME_PROFILE}.
* If not, it throws a {@link SecurityException}.