diff options
Diffstat (limited to 'android/content/pm/dex/ArtManager.java')
-rw-r--r-- | android/content/pm/dex/ArtManager.java | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/android/content/pm/dex/ArtManager.java b/android/content/pm/dex/ArtManager.java new file mode 100644 index 00000000..201cd8d3 --- /dev/null +++ b/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; + } + } +} |