diff options
| author | 2017-11-29 18:26:55 -0800 | |
|---|---|---|
| committer | 2017-12-06 18:29:06 +0000 | |
| commit | fd9f8ae973122a50f336e38c386ecbc0095d8adc (patch) | |
| tree | af3bab0b76d62a15952f9d2fadddc3c2aed78b3f | |
| parent | 839edb1781264eb268711075add1e4e31a18caed (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
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}. |