Add SystemApis to expose runtime profile information
The API allows a system apps which acquired
{@code android.permission.READ_RUNTIME_PROFILE} to snapshot the runtime
profiles of installed packages.
The API is implemented in a new service class (AndroidRuntimeManager)
accessible from the context using
context().getPackageManager().getAndroidRuntimeManager().
The main functionality is exposed as a one way call into the
AndroidRuntimeManager with the result being posted on a callback. The
profile is available to the caller as a read-only ParcelFileDescriptor.
This CL only adds the API interfaces and validation. It does not fully
implement the functionality.
oneway void snapshotRuntimeProfile(in String packageName,
in String codePath, in ISnapshotRuntimeProfileCallback callback)
Bug: 30934496
Test: gts-tradefed -m GtsAndroidRuntimeManagerHostTestCases
Change-Id: Iaa6be4715840f24508acba3162ea9c1ab725bd38
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 005b7c3..1dbdb59 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -55,6 +55,7 @@
import android.content.pm.SharedLibraryInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
+import android.content.pm.dex.ArtManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
@@ -121,6 +122,8 @@
private UserManager mUserManager;
@GuardedBy("mLock")
private PackageInstaller mInstaller;
+ @GuardedBy("mLock")
+ private ArtManager mArtManager;
@GuardedBy("mDelegates")
private final ArrayList<MoveCallbackDelegate> mDelegates = new ArrayList<>();
@@ -2750,4 +2753,18 @@
throw e.rethrowAsRuntimeException();
}
}
+
+ @Override
+ public ArtManager getArtManager() {
+ synchronized (mLock) {
+ if (mArtManager == null) {
+ try {
+ mArtManager = new ArtManager(mPM.getArtManager());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return mArtManager;
+ }
+ }
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 64d33d5..56a0def 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -48,6 +48,7 @@
import android.content.pm.UserInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
+import android.content.pm.dex.IArtManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
@@ -657,4 +658,6 @@
ComponentName getInstantAppInstallerComponent();
String getInstantAppAndroidId(String packageName, int userId);
+
+ IArtManager getArtManager();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f796aab..a5cc902 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -42,6 +42,7 @@
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.dex.ArtManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
@@ -5842,4 +5843,14 @@
@SystemApi
public abstract void registerDexModule(String dexModulePath,
@Nullable DexModuleRegisterCallback callback);
+
+ /**
+ * Returns the {@link ArtManager} associated with this package manager.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull ArtManager getArtManager() {
+ throw new UnsupportedOperationException("getArtManager not implemented in subclass");
+ }
}
diff --git a/core/java/android/content/pm/dex/ArtManager.java b/core/java/android/content/pm/dex/ArtManager.java
new file mode 100644
index 0000000..201cd8d
--- /dev/null
+++ b/core/java/android/content/pm/dex/ArtManager.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.dex;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Slog;
+
+/**
+ * Class for retrieving various kinds of information related to the runtime artifacts of
+ * packages that are currently installed on the device.
+ *
+ * @hide
+ */
+@SystemApi
+public class ArtManager {
+ private static final String TAG = "ArtManager";
+
+ /** The snapshot failed because the package was not found. */
+ public static final int SNAPSHOT_FAILED_PACKAGE_NOT_FOUND = 0;
+ /** The snapshot failed because the package code path does not exist. */
+ public static final int SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND = 1;
+ /** The snapshot failed because of an internal error (e.g. error during opening profiles). */
+ public static final int SNAPSHOT_FAILED_INTERNAL_ERROR = 2;
+
+ private IArtManager mArtManager;
+
+ /**
+ * @hide
+ */
+ public ArtManager(@NonNull IArtManager manager) {
+ mArtManager = manager;
+ }
+
+ /**
+ * Snapshots the runtime profile for an apk belonging to the package {@code packageName}.
+ * The apk is identified by {@code codePath}. The calling process must have
+ * {@code android.permission.READ_RUNTIME_PROFILE} permission.
+ *
+ * The result will be posted on {@code handler} using the given {@code callback}.
+ * The profile being available as a read-only {@link android.os.ParcelFileDescriptor}.
+ *
+ * @param packageName the target package name
+ * @param codePath the code path for which the profile should be retrieved
+ * @param callback the callback which should be used for the result
+ * @param handler the handler which should be used to post the result
+ */
+ @RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
+ public void snapshotRuntimeProfile(@NonNull String packageName, @NonNull String codePath,
+ @NonNull SnapshotRuntimeProfileCallback callback, @NonNull Handler handler) {
+ Slog.d(TAG, "Requesting profile snapshot for " + packageName + ":" + codePath);
+
+ SnapshotRuntimeProfileCallbackDelegate delegate =
+ new SnapshotRuntimeProfileCallbackDelegate(callback, handler.getLooper());
+ try {
+ mArtManager.snapshotRuntimeProfile(packageName, codePath, delegate);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Returns true if runtime profiles are enabled, false otherwise.
+ *
+ * The calling process must have {@code android.permission.READ_RUNTIME_PROFILE} permission.
+ */
+ @RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
+ public boolean isRuntimeProfilingEnabled() {
+ try {
+ return mArtManager.isRuntimeProfilingEnabled();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ return false;
+ }
+
+ /**
+ * Callback used for retrieving runtime profiles.
+ */
+ public abstract static class SnapshotRuntimeProfileCallback {
+ /**
+ * Called when the profile snapshot finished with success.
+ *
+ * @param profileReadFd the file descriptor that can be used to read the profile. Note that
+ * the file might be empty (which is valid profile).
+ */
+ public abstract void onSuccess(ParcelFileDescriptor profileReadFd);
+
+ /**
+ * Called when the profile snapshot finished with an error.
+ *
+ * @param errCode the error code {@see SNAPSHOT_FAILED_PACKAGE_NOT_FOUND,
+ * SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND, SNAPSHOT_FAILED_INTERNAL_ERROR}.
+ */
+ public abstract void onError(int errCode);
+ }
+
+ private static class SnapshotRuntimeProfileCallbackDelegate
+ extends android.content.pm.dex.ISnapshotRuntimeProfileCallback.Stub
+ implements Handler.Callback {
+ private static final int MSG_SNAPSHOT_OK = 1;
+ private static final int MSG_ERROR = 2;
+ private final ArtManager.SnapshotRuntimeProfileCallback mCallback;
+ private final Handler mHandler;
+
+ private SnapshotRuntimeProfileCallbackDelegate(
+ ArtManager.SnapshotRuntimeProfileCallback callback, Looper looper) {
+ mCallback = callback;
+ mHandler = new Handler(looper, this);
+ }
+
+ @Override
+ public void onSuccess(ParcelFileDescriptor profileReadFd) {
+ mHandler.obtainMessage(MSG_SNAPSHOT_OK, profileReadFd).sendToTarget();
+ }
+
+ @Override
+ public void onError(int errCode) {
+ mHandler.obtainMessage(MSG_ERROR, errCode, 0).sendToTarget();
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SNAPSHOT_OK:
+ mCallback.onSuccess((ParcelFileDescriptor) msg.obj);
+ break;
+ case MSG_ERROR:
+ mCallback.onError(msg.arg1);
+ break;
+ default: return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/core/java/android/content/pm/dex/IArtManager.aidl b/core/java/android/content/pm/dex/IArtManager.aidl
new file mode 100644
index 0000000..8cbb452
--- /dev/null
+++ b/core/java/android/content/pm/dex/IArtManager.aidl
@@ -0,0 +1,44 @@
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm.dex;
+
+import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
+
+/**
+ * A system service that provides access to runtime and compiler artifacts.
+ *
+ * @hide
+ */
+interface IArtManager {
+ /**
+ * Snapshots the runtime profile for an apk belonging to the package {@param packageName}.
+ * The apk is identified by {@param codePath}. The calling process must have
+ * {@code android.permission.READ_RUNTIME_PROFILE} permission.
+ *
+ * The result will be posted on {@param callback} with the profile being available as a
+ * read-only {@link android.os.ParcelFileDescriptor}.
+ */
+ oneway void snapshotRuntimeProfile(in String packageName,
+ in String codePath, in ISnapshotRuntimeProfileCallback callback);
+
+ /**
+ * Returns true if runtime profiles are enabled, false otherwise.
+ *
+ * The calling process must have {@code android.permission.READ_RUNTIME_PROFILE} permission.
+ */
+ boolean isRuntimeProfilingEnabled();
+}
diff --git a/core/java/android/content/pm/dex/ISnapshotRuntimeProfileCallback.aidl b/core/java/android/content/pm/dex/ISnapshotRuntimeProfileCallback.aidl
new file mode 100644
index 0000000..3b4838f
--- /dev/null
+++ b/core/java/android/content/pm/dex/ISnapshotRuntimeProfileCallback.aidl
@@ -0,0 +1,29 @@
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm.dex;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Callback used to post the result of a profile-snapshot operation.
+ *
+ * @hide
+ */
+oneway interface ISnapshotRuntimeProfileCallback {
+ void onSuccess(in ParcelFileDescriptor profileReadFd);
+ void onError(int errCode);
+}