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
This commit is contained in:
@@ -134,6 +134,8 @@ java_library {
|
||||
"core/java/android/content/pm/IPackageStatsObserver.aidl",
|
||||
"core/java/android/content/pm/IPinItemRequest.aidl",
|
||||
"core/java/android/content/pm/IShortcutService.aidl",
|
||||
"core/java/android/content/pm/dex/IArtManager.aidl",
|
||||
"core/java/android/content/pm/dex/ISnapshotRuntimeProfileCallback.aidl",
|
||||
"core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl",
|
||||
"core/java/android/database/IContentObserver.aidl",
|
||||
":libcamera_client_aidl",
|
||||
|
||||
@@ -126,6 +126,7 @@ package android {
|
||||
field public static final java.lang.String READ_PRINT_SERVICES = "android.permission.READ_PRINT_SERVICES";
|
||||
field public static final java.lang.String READ_PRINT_SERVICE_RECOMMENDATIONS = "android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS";
|
||||
field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
|
||||
field public static final java.lang.String READ_RUNTIME_PROFILES = "android.permission.READ_RUNTIME_PROFILES";
|
||||
field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
|
||||
field public static final java.lang.String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL";
|
||||
field public static final java.lang.String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
|
||||
@@ -843,6 +844,7 @@ package android.content.pm {
|
||||
public abstract class PackageManager {
|
||||
method public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
|
||||
method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
|
||||
method public android.content.pm.dex.ArtManager getArtManager();
|
||||
method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
|
||||
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
|
||||
method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
|
||||
@@ -950,6 +952,24 @@ package android.content.pm {
|
||||
|
||||
}
|
||||
|
||||
package android.content.pm.dex {
|
||||
|
||||
public class ArtManager {
|
||||
method public boolean isRuntimeProfilingEnabled();
|
||||
method public void snapshotRuntimeProfile(java.lang.String, java.lang.String, android.content.pm.dex.ArtManager.SnapshotRuntimeProfileCallback, android.os.Handler);
|
||||
field public static final int SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND = 1; // 0x1
|
||||
field public static final int SNAPSHOT_FAILED_INTERNAL_ERROR = 2; // 0x2
|
||||
field public static final int SNAPSHOT_FAILED_PACKAGE_NOT_FOUND = 0; // 0x0
|
||||
}
|
||||
|
||||
public static abstract class ArtManager.SnapshotRuntimeProfileCallback {
|
||||
ctor public ArtManager.SnapshotRuntimeProfileCallback();
|
||||
method public abstract void onError(int);
|
||||
method public abstract void onSuccess(android.os.ParcelFileDescriptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.content.pm.permission {
|
||||
|
||||
public final class RuntimePermissionPresentationInfo implements android.os.Parcelable {
|
||||
|
||||
@@ -55,6 +55,7 @@ import android.content.pm.ServiceInfo;
|
||||
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 @@ public class ApplicationPackageManager extends PackageManager {
|
||||
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 @@ public class ApplicationPackageManager extends PackageManager {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.content.pm.ServiceInfo;
|
||||
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 @@ interface IPackageManager {
|
||||
ComponentName getInstantAppInstallerComponent();
|
||||
|
||||
String getInstantAppAndroidId(String packageName, int userId);
|
||||
|
||||
IArtManager getArtManager();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.content.Intent;
|
||||
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 @@ public abstract class PackageManager {
|
||||
@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");
|
||||
}
|
||||
}
|
||||
|
||||
156
core/java/android/content/pm/dex/ArtManager.java
Normal file
156
core/java/android/content/pm/dex/ArtManager.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
core/java/android/content/pm/dex/IArtManager.aidl
Normal file
44
core/java/android/content/pm/dex/IArtManager.aidl
Normal file
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -3616,6 +3616,11 @@
|
||||
<permission android:name="android.permission.ACCESS_SHORTCUTS"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- @SystemApi Allows an application to read the runtime profiles of other apps.
|
||||
@hide <p>Not for use by third-party applications. -->
|
||||
<permission android:name="android.permission.READ_RUNTIME_PROFILES"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<application android:process="system"
|
||||
android:persistent="true"
|
||||
android:hasCode="false"
|
||||
|
||||
@@ -111,7 +111,6 @@ import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
|
||||
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
|
||||
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
|
||||
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
|
||||
import static dalvik.system.DexFile.getNonProfileGuidedCompilerFilter;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.IntDef;
|
||||
@@ -187,6 +186,7 @@ import android.content.pm.UserInfo;
|
||||
import android.content.pm.VerifierDeviceIdentity;
|
||||
import android.content.pm.VerifierInfo;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.content.pm.dex.IArtManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -265,14 +265,12 @@ import com.android.internal.content.PackageHelper;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.os.IParcelFileDescriptorFactory;
|
||||
import com.android.internal.os.RoSystemProperties;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.os.Zygote;
|
||||
import com.android.internal.telephony.CarrierAppUtils;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.ConcurrentUtils;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.Preconditions;
|
||||
@@ -292,6 +290,7 @@ import com.android.server.net.NetworkPolicyManagerInternal;
|
||||
import com.android.server.pm.Installer.InstallerException;
|
||||
import com.android.server.pm.Settings.DatabaseVersion;
|
||||
import com.android.server.pm.Settings.VersionInfo;
|
||||
import com.android.server.pm.dex.ArtManagerService;
|
||||
import com.android.server.pm.dex.DexLogger;
|
||||
import com.android.server.pm.dex.DexManager;
|
||||
import com.android.server.pm.dex.DexoptOptions;
|
||||
@@ -307,30 +306,23 @@ import com.android.server.pm.permission.PermissionsState.PermissionState;
|
||||
import com.android.server.storage.DeviceStorageMonitorInternal;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
import dalvik.system.DexFile;
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.io.Streams;
|
||||
import libcore.util.EmptyArray;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -341,15 +333,12 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
@@ -363,7 +352,6 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* Keep track of all those APKs everywhere.
|
||||
@@ -939,6 +927,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
final PackageInstallerService mInstallerService;
|
||||
|
||||
final ArtManagerService mArtManagerService;
|
||||
|
||||
private final PackageDexOptimizer mPackageDexOptimizer;
|
||||
// DexManager handles the usage of dex files (e.g. secondary files, whether or not a package
|
||||
// is used by other apps).
|
||||
@@ -3047,6 +3037,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
mInstallerService = new PackageInstallerService(context, this);
|
||||
mArtManagerService = new ArtManagerService(this);
|
||||
final Pair<ComponentName, String> instantAppResolverComponent =
|
||||
getInstantAppResolverLPr();
|
||||
if (instantAppResolverComponent != null) {
|
||||
@@ -22273,6 +22264,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
return mInstallerService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IArtManager getArtManager() {
|
||||
return mArtManagerService;
|
||||
}
|
||||
|
||||
private boolean userNeedsBadging(int userId) {
|
||||
int index = mUserNeedsBadging.indexOfKey(userId);
|
||||
if (index < 0) {
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 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 com.android.server.pm.dex;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.dex.ArtManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
/**
|
||||
* A system service that provides access to runtime and compiler artifacts.
|
||||
*
|
||||
* This service is not accessed by users directly, instead one uses an instance of
|
||||
* {@link ArtManager}, which can be accessed via {@link PackageManager} as follows:
|
||||
* <p/>
|
||||
* {@code context().getPackageManager().getArtManager();}
|
||||
* <p class="note">
|
||||
* Note: Accessing runtime artifacts may require extra permissions. For example querying the
|
||||
* runtime profiles of apps requires {@link android.Manifest.permission#READ_RUNTIME_PROFILES}
|
||||
* which is a system-level permission that will not be granted to normal apps.
|
||||
*/
|
||||
public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
private static final String TAG = "ArtManagerService";
|
||||
|
||||
private static boolean DEBUG = false;
|
||||
private static boolean DEBUG_IGNORE_PERMISSIONS = false;
|
||||
|
||||
private final IPackageManager mPackageManager;
|
||||
private final Handler mHandler;
|
||||
|
||||
public ArtManagerService(IPackageManager pm) {
|
||||
mPackageManager = pm;
|
||||
mHandler = new Handler(BackgroundThread.getHandler().getLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void snapshotRuntimeProfile(String packageName, String codePath,
|
||||
ISnapshotRuntimeProfileCallback callback) {
|
||||
// Sanity checks on the arguments.
|
||||
Preconditions.checkStringNotEmpty(packageName);
|
||||
Preconditions.checkStringNotEmpty(codePath);
|
||||
Preconditions.checkNotNull(callback);
|
||||
|
||||
// Verify that the caller has the right permissions.
|
||||
checkReadRuntimeProfilePermission();
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Requested snapshot for " + packageName + ":" + codePath);
|
||||
}
|
||||
|
||||
PackageInfo info = null;
|
||||
try {
|
||||
// Note that we use the default user 0 to retrieve the package info.
|
||||
// This doesn't really matter because for user 0 we always get a package back (even if
|
||||
// it's not installed for the user 0). It is ok because we only care about the code
|
||||
// paths and not if the package is enabled or not for the user.
|
||||
|
||||
// TODO(calin): consider adding an API to PMS which can retrieve the
|
||||
// PackageParser.Package.
|
||||
info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0);
|
||||
} catch (RemoteException ignored) {
|
||||
// Should not happen.
|
||||
}
|
||||
if (info == null) {
|
||||
postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean pathFound = info.applicationInfo.getBaseCodePath().equals(codePath);
|
||||
String[] splitCodePaths = info.applicationInfo.getSplitCodePaths();
|
||||
if (!pathFound && (splitCodePaths != null)) {
|
||||
for (String path : splitCodePaths) {
|
||||
if (path.equals(codePath)) {
|
||||
pathFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pathFound) {
|
||||
postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// All good, move forward and get the profile.
|
||||
postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRuntimeProfilingEnabled() {
|
||||
// Verify that the caller has the right permissions.
|
||||
checkReadRuntimeProfilePermission();
|
||||
|
||||
return SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post {@link ISnapshotRuntimeProfileCallback#onError(int)} with the given error message
|
||||
* on the internal {@code mHandler}.
|
||||
*/
|
||||
private void postError(ISnapshotRuntimeProfileCallback callback, String packageName,
|
||||
int errCode) {
|
||||
mHandler.post(() -> {
|
||||
try {
|
||||
callback.onError(errCode);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "Failed to callback 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}.
|
||||
*/
|
||||
private void checkReadRuntimeProfilePermission() {
|
||||
if (DEBUG_IGNORE_PERMISSIONS) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int result = mPackageManager.checkUidPermission(
|
||||
Manifest.permission.READ_RUNTIME_PROFILES, Binder.getCallingUid());
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("You need "
|
||||
+ Manifest.permission.READ_RUNTIME_PROFILES
|
||||
+ " permission to snapshot profiles.");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Should not happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import android.content.pm.ServiceInfo;
|
||||
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.Rect;
|
||||
@@ -1174,4 +1175,12 @@ public class MockPackageManager extends PackageManager {
|
||||
@Nullable DexModuleRegisterCallback callback) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public ArtManager getArtManager() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user