Merge "Protect usage data with OP_GET_USAGE_STATS." into pi-dev
am: ddb15c471c
Change-Id: Ieccbac3a53b14f196a3ceb7924f7bb6880660c97
This commit is contained in:
@@ -2831,7 +2831,7 @@ public class ApplicationPackageManager extends PackageManager {
|
||||
synchronized (mLock) {
|
||||
if (mArtManager == null) {
|
||||
try {
|
||||
mArtManager = new ArtManager(mPM.getArtManager());
|
||||
mArtManager = new ArtManager(mContext, mPM.getArtManager());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -16,12 +16,16 @@
|
||||
|
||||
package android.content.pm.dex;
|
||||
|
||||
import static android.Manifest.permission.PACKAGE_USAGE_STATS;
|
||||
import static android.Manifest.permission.READ_RUNTIME_PROFILES;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
@@ -62,13 +66,14 @@ public class ArtManager {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ProfileType {}
|
||||
|
||||
|
||||
private IArtManager mArtManager;
|
||||
private final Context mContext;
|
||||
private final IArtManager mArtManager;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public ArtManager(@NonNull IArtManager manager) {
|
||||
public ArtManager(@NonNull Context context, @NonNull IArtManager manager) {
|
||||
mContext = context;
|
||||
mArtManager = manager;
|
||||
}
|
||||
|
||||
@@ -99,7 +104,7 @@ public class ArtManager {
|
||||
* @param callback the callback which should be used for the result
|
||||
* @param executor the executor which should be used to post the result
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
|
||||
@RequiresPermission(allOf = { READ_RUNTIME_PROFILES, PACKAGE_USAGE_STATS })
|
||||
public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName,
|
||||
@Nullable String codePath, @NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull SnapshotRuntimeProfileCallback callback) {
|
||||
@@ -108,9 +113,10 @@ public class ArtManager {
|
||||
SnapshotRuntimeProfileCallbackDelegate delegate =
|
||||
new SnapshotRuntimeProfileCallbackDelegate(callback, executor);
|
||||
try {
|
||||
mArtManager.snapshotRuntimeProfile(profileType, packageName, codePath, delegate);
|
||||
mArtManager.snapshotRuntimeProfile(profileType, packageName, codePath, delegate,
|
||||
mContext.getOpPackageName());
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowAsRuntimeException();
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,14 +128,13 @@ public class ArtManager {
|
||||
* @param profileType can be either {@link ArtManager#PROFILE_APPS}
|
||||
* or {@link ArtManager#PROFILE_BOOT_IMAGE}
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
|
||||
@RequiresPermission(allOf = { READ_RUNTIME_PROFILES, PACKAGE_USAGE_STATS })
|
||||
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType) {
|
||||
try {
|
||||
return mArtManager.isRuntimeProfilingEnabled(profileType);
|
||||
return mArtManager.isRuntimeProfilingEnabled(profileType, mContext.getOpPackageName());
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowAsRuntimeException();
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,8 +44,8 @@ interface IArtManager {
|
||||
* {@link ArtManager#isRuntimeProfilingEnabled(int)} does not return true for the given
|
||||
* {@code profileType}.
|
||||
*/
|
||||
oneway void snapshotRuntimeProfile(int profileType, in String packageName,
|
||||
in String codePath, in ISnapshotRuntimeProfileCallback callback);
|
||||
void snapshotRuntimeProfile(int profileType, in String packageName,
|
||||
in String codePath, in ISnapshotRuntimeProfileCallback callback, String callingPackage);
|
||||
|
||||
/**
|
||||
* Returns true if runtime profiles are enabled for the given type, false otherwise.
|
||||
@@ -54,5 +54,5 @@ interface IArtManager {
|
||||
*
|
||||
* @param profileType
|
||||
*/
|
||||
boolean isRuntimeProfilingEnabled(int profileType);
|
||||
boolean isRuntimeProfilingEnabled(int profileType, String callingPackage);
|
||||
}
|
||||
|
||||
@@ -2462,7 +2462,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
installer, mInstallLock);
|
||||
mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock,
|
||||
dexManagerListener);
|
||||
mArtManagerService = new ArtManagerService(this, installer, mInstallLock);
|
||||
mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
|
||||
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
|
||||
|
||||
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
package com.android.server.pm.dex;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageInfo;
|
||||
@@ -38,7 +39,9 @@ import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.system.Os;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
@@ -47,14 +50,17 @@ import com.android.server.LocalServices;
|
||||
import com.android.server.pm.Installer;
|
||||
import com.android.server.pm.Installer.InstallerException;
|
||||
import com.android.server.pm.PackageManagerServiceCompilerMapping;
|
||||
|
||||
import dalvik.system.DexFile;
|
||||
import dalvik.system.VMRuntime;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.util.NonNull;
|
||||
import libcore.util.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
/**
|
||||
* A system service that provides access to runtime and compiler artifacts.
|
||||
*
|
||||
@@ -69,9 +75,7 @@ import libcore.util.Nullable;
|
||||
*/
|
||||
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 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
// Package name used to create the profile directory layout when
|
||||
// taking a snapshot of the boot image profile.
|
||||
@@ -79,6 +83,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
// Profile name used for the boot image profile.
|
||||
private static final String BOOT_IMAGE_PROFILE_NAME = "android.prof";
|
||||
|
||||
private final Context mContext;
|
||||
private final IPackageManager mPackageManager;
|
||||
private final Object mInstallLock;
|
||||
@GuardedBy("mInstallLock")
|
||||
@@ -90,7 +95,9 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
verifyTronLoggingConstants();
|
||||
}
|
||||
|
||||
public ArtManagerService(IPackageManager pm, Installer installer, Object installLock) {
|
||||
public ArtManagerService(Context context, IPackageManager pm, Installer installer,
|
||||
Object installLock) {
|
||||
mContext = context;
|
||||
mPackageManager = pm;
|
||||
mInstaller = installer;
|
||||
mInstallLock = installLock;
|
||||
@@ -99,9 +106,37 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
LocalServices.addService(ArtManagerInternal.class, new ArtManagerInternalImpl());
|
||||
}
|
||||
|
||||
private boolean checkPermission(int callingUid, String callingPackage) {
|
||||
// Callers always need this permission
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.READ_RUNTIME_PROFILES, TAG);
|
||||
|
||||
// Callers also need the ability to read usage statistics
|
||||
switch (mContext.getSystemService(AppOpsManager.class)
|
||||
.noteOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage)) {
|
||||
case AppOpsManager.MODE_ALLOWED:
|
||||
return true;
|
||||
case AppOpsManager.MODE_DEFAULT:
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.PACKAGE_USAGE_STATS, TAG);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName,
|
||||
@Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback) {
|
||||
@Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback,
|
||||
String callingPackage) {
|
||||
if (!checkPermission(Binder.getCallingUid(), callingPackage)) {
|
||||
try {
|
||||
callback.onError(ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity checks on the arguments.
|
||||
Preconditions.checkNotNull(callback);
|
||||
|
||||
@@ -111,9 +146,8 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
Preconditions.checkStringNotEmpty(packageName);
|
||||
}
|
||||
|
||||
// Verify that the caller has the right permissions and that the runtime profiling is
|
||||
// enabled. The call to isRuntimePermissions will checkReadRuntimeProfilePermission.
|
||||
if (!isRuntimeProfilingEnabled(profileType)) {
|
||||
// Verify that runtime profiling is enabled.
|
||||
if (!isRuntimeProfilingEnabled(profileType, callingPackage)) {
|
||||
throw new IllegalStateException("Runtime profiling is not enabled for " + profileType);
|
||||
}
|
||||
|
||||
@@ -231,9 +265,10 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType) {
|
||||
// Verify that the caller has the right permissions.
|
||||
checkReadRuntimeProfilePermission();
|
||||
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType, String callingPackage) {
|
||||
if (!checkPermission(Binder.getCallingUid(), callingPackage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (profileType) {
|
||||
case ArtManager.PROFILE_APPS :
|
||||
@@ -305,27 +340,6 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the application profiles.
|
||||
* For all code paths:
|
||||
|
||||
Reference in New Issue
Block a user