blob: 201cd8d32cc1cc28a8d561bca2db6bcbc2dec46c [file] [log] [blame]
Calin Juravle45f8b292017-11-07 18:49:43 -08001/**
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm.dex;
18
19import android.annotation.NonNull;
20import android.annotation.RequiresPermission;
21import android.annotation.SystemApi;
22import android.os.Handler;
23import android.os.Looper;
24import android.os.Message;
25import android.os.ParcelFileDescriptor;
26import android.os.RemoteException;
27import android.util.Slog;
28
29/**
30 * Class for retrieving various kinds of information related to the runtime artifacts of
31 * packages that are currently installed on the device.
32 *
33 * @hide
34 */
35@SystemApi
36public class ArtManager {
37 private static final String TAG = "ArtManager";
38
39 /** The snapshot failed because the package was not found. */
40 public static final int SNAPSHOT_FAILED_PACKAGE_NOT_FOUND = 0;
41 /** The snapshot failed because the package code path does not exist. */
42 public static final int SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND = 1;
43 /** The snapshot failed because of an internal error (e.g. error during opening profiles). */
44 public static final int SNAPSHOT_FAILED_INTERNAL_ERROR = 2;
45
46 private IArtManager mArtManager;
47
48 /**
49 * @hide
50 */
51 public ArtManager(@NonNull IArtManager manager) {
52 mArtManager = manager;
53 }
54
55 /**
56 * Snapshots the runtime profile for an apk belonging to the package {@code packageName}.
57 * The apk is identified by {@code codePath}. The calling process must have
58 * {@code android.permission.READ_RUNTIME_PROFILE} permission.
59 *
60 * The result will be posted on {@code handler} using the given {@code callback}.
61 * The profile being available as a read-only {@link android.os.ParcelFileDescriptor}.
62 *
63 * @param packageName the target package name
64 * @param codePath the code path for which the profile should be retrieved
65 * @param callback the callback which should be used for the result
66 * @param handler the handler which should be used to post the result
67 */
68 @RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
69 public void snapshotRuntimeProfile(@NonNull String packageName, @NonNull String codePath,
70 @NonNull SnapshotRuntimeProfileCallback callback, @NonNull Handler handler) {
71 Slog.d(TAG, "Requesting profile snapshot for " + packageName + ":" + codePath);
72
73 SnapshotRuntimeProfileCallbackDelegate delegate =
74 new SnapshotRuntimeProfileCallbackDelegate(callback, handler.getLooper());
75 try {
76 mArtManager.snapshotRuntimeProfile(packageName, codePath, delegate);
77 } catch (RemoteException e) {
78 e.rethrowAsRuntimeException();
79 }
80 }
81
82 /**
83 * Returns true if runtime profiles are enabled, false otherwise.
84 *
85 * The calling process must have {@code android.permission.READ_RUNTIME_PROFILE} permission.
86 */
87 @RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
88 public boolean isRuntimeProfilingEnabled() {
89 try {
90 return mArtManager.isRuntimeProfilingEnabled();
91 } catch (RemoteException e) {
92 e.rethrowAsRuntimeException();
93 }
94 return false;
95 }
96
97 /**
98 * Callback used for retrieving runtime profiles.
99 */
100 public abstract static class SnapshotRuntimeProfileCallback {
101 /**
102 * Called when the profile snapshot finished with success.
103 *
104 * @param profileReadFd the file descriptor that can be used to read the profile. Note that
105 * the file might be empty (which is valid profile).
106 */
107 public abstract void onSuccess(ParcelFileDescriptor profileReadFd);
108
109 /**
110 * Called when the profile snapshot finished with an error.
111 *
112 * @param errCode the error code {@see SNAPSHOT_FAILED_PACKAGE_NOT_FOUND,
113 * SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND, SNAPSHOT_FAILED_INTERNAL_ERROR}.
114 */
115 public abstract void onError(int errCode);
116 }
117
118 private static class SnapshotRuntimeProfileCallbackDelegate
119 extends android.content.pm.dex.ISnapshotRuntimeProfileCallback.Stub
120 implements Handler.Callback {
121 private static final int MSG_SNAPSHOT_OK = 1;
122 private static final int MSG_ERROR = 2;
123 private final ArtManager.SnapshotRuntimeProfileCallback mCallback;
124 private final Handler mHandler;
125
126 private SnapshotRuntimeProfileCallbackDelegate(
127 ArtManager.SnapshotRuntimeProfileCallback callback, Looper looper) {
128 mCallback = callback;
129 mHandler = new Handler(looper, this);
130 }
131
132 @Override
133 public void onSuccess(ParcelFileDescriptor profileReadFd) {
134 mHandler.obtainMessage(MSG_SNAPSHOT_OK, profileReadFd).sendToTarget();
135 }
136
137 @Override
138 public void onError(int errCode) {
139 mHandler.obtainMessage(MSG_ERROR, errCode, 0).sendToTarget();
140 }
141
142 @Override
143 public boolean handleMessage(Message msg) {
144 switch (msg.what) {
145 case MSG_SNAPSHOT_OK:
146 mCallback.onSuccess((ParcelFileDescriptor) msg.obj);
147 break;
148 case MSG_ERROR:
149 mCallback.onError(msg.arg1);
150 break;
151 default: return false;
152 }
153 return true;
154 }
155 }
156}