Merge "Allow UiAutomation to adopt the shell permission indentity"

This commit is contained in:
Sooraj Sasindran
2019-02-22 00:41:29 +00:00
committed by Gerrit Code Review
16 changed files with 466 additions and 50 deletions

View File

@@ -6117,8 +6117,10 @@ package android.app {
}
public final class UiAutomation {
method public void adoptShellPermissionIdentity();
method public void clearWindowAnimationFrameStats();
method public boolean clearWindowContentFrameStats(int);
method public void dropShellPermissionIdentity();
method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
method public android.os.ParcelFileDescriptor executeShellCommand(String);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);

View File

@@ -263,7 +263,9 @@ package android.content.pm {
method public abstract String getPermissionControllerPackageName();
method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method public abstract boolean isPermissionReviewModeEnabled();
method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000

View File

@@ -2513,7 +2513,7 @@ public class AppOpsManager {
*/
public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
try {
return mService.noteProxyOperation(op, mContext.getOpPackageName(),
return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(),
Binder.getCallingUid(), proxiedPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();

View File

@@ -18,12 +18,55 @@ package android.app;
import android.util.SparseIntArray;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.TriFunction;
/**
* App ops service local interface.
*
* @hide Only for use within the system server.
*/
public abstract class AppOpsManagerInternal {
/** Interface to override app ops checks via composition */
public interface CheckOpsDelegate {
/**
* Allows overriding check operation behavior.
*
* @param code The op code to check.
* @param uid The UID for which to check.
* @param packageName The package for which to check.
* @param superImpl The super implementation.
* @return The app op check result.
*/
int checkOperation(int code, int uid, String packageName,
TriFunction<Integer, Integer, String, Integer> superImpl);
/**
* Allows overriding check audio operation behavior.
*
* @param code The op code to check.
* @param usage The audio op usage.
* @param uid The UID for which to check.
* @param packageName The package for which to check.
* @param superImpl The super implementation.
* @return The app op check result.
*/
int checkAudioOperation(int code, int usage, int uid, String packageName,
QuadFunction<Integer, Integer, Integer, String, Integer> superImpl);
/**
* Allows overriding note operation behavior.
*
* @param code The op code to note.
* @param uid The UID for which to note.
* @param packageName The package for which to note.
* @param superImpl The super implementation.
* @return The app op note result.
*/
int noteOperation(int code, int uid, String packageName,
TriFunction<Integer, Integer, String, Integer> superImpl);
}
/**
* Set the currently configured device and profile owners. Specifies the package uid (value)
* that has been configured for each user (key) that has one. These will be allowed privileged

View File

@@ -714,4 +714,19 @@ interface IActivityManager {
/** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
void alwaysShowUnsupportedCompileSdkWarning(in ComponentName activity);
/**
* Method for the shell UID to start deletating its permission identity to an
* active instrumenation. The shell can delegate permissions only to one active
* instrumentation at a time. An active instrumentation is one running and
* started from the shell.
*/
void startDelegateShellPermissionIdentity(int uid);
/**
* Method for the shell UID to stop deletating its permission identity to an
* active instrumenation. An active instrumentation is one running and
* started from the shell.
*/
void stopDelegateShellPermissionIdentity();
}

View File

@@ -47,7 +47,8 @@ interface IUiAutomationConnection {
in ParcelFileDescriptor source);
void grantRuntimePermission(String packageName, String permission, int userId);
void revokeRuntimePermission(String packageName, String permission, int userId);
void adoptShellPermissionIdentity(int uid);
void dropShellPermissionIdentity();
// Called from the system process.
oneway void shutdown();
}

View File

@@ -35,6 +35,7 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -52,6 +53,7 @@ import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import com.android.internal.util.function.pooled.PooledLambda;
import libcore.io.IoUtils;
import java.io.IOException;
@@ -351,6 +353,46 @@ public final class UiAutomation {
mIsDestroyed = true;
}
/**
* Adopt the permission identity of the shell UID. This allows you to call APIs protected
* permissions which normal apps cannot hold but are granted to the shell UID. If you
* already adopted the shell permission identity this method would be a no-op.
* Note that your permission state becomes that of the shell UID and it is not a
* combination of your and the shell UID permissions.
*
* @see #dropShellPermissionIdentity()
*/
public void adoptShellPermissionIdentity() {
synchronized (mLock) {
throwIfNotConnectedLocked();
}
try {
// Calling out without a lock held.
mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid());
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error executing adopting shell permission identity!", re);
}
}
/**
* Drop the shell permission identity adopted by a previous call to
* {@link #adoptShellPermissionIdentity()}. If you did not adopt the shell permission
* identity this method would be a no-op.
*
* @see #adoptShellPermissionIdentity()
*/
public void dropShellPermissionIdentity() {
synchronized (mLock) {
throwIfNotConnectedLocked();
}
try {
// Calling out without a lock held.
mUiAutomationConnection.dropShellPermissionIdentity();
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error executing dropping shell permission identity!", re);
}
}
/**
* Performs a global action. Such an action can be performed at any moment
* regardless of the current application or user location in that application.
@@ -1004,6 +1046,8 @@ public final class UiAutomation {
*
* @param command The command to execute.
* @return A file descriptor to the standard output stream.
*
* @see #adoptShellPermissionIdentity()
*/
public ParcelFileDescriptor executeShellCommand(String command) {
synchronized (mLock) {
@@ -1086,22 +1130,6 @@ public final class UiAutomation {
return result;
}
private static float getDegreesForRotation(int value) {
switch (value) {
case Surface.ROTATION_90: {
return 360f - 90f;
}
case Surface.ROTATION_180: {
return 360f - 180f;
}
case Surface.ROTATION_270: {
return 360f - 270f;
} default: {
return 0;
}
}
}
private boolean isConnectedLocked() {
return mConnectionId != CONNECTION_ID_UNDEFINED;
}

View File

@@ -31,6 +31,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
import android.view.IWindowManager;
import android.view.InputEvent;
import android.view.SurfaceControl;
@@ -38,7 +39,6 @@ import android.view.WindowAnimationFrameStats;
import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
import android.util.Log;
import libcore.io.IoUtils;
@@ -72,6 +72,9 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
private final IPackageManager mPackageManager = IPackageManager.Stub
.asInterface(ServiceManager.getService("package"));
private final IActivityManager mActivityManager = IActivityManager.Stub
.asInterface(ServiceManager.getService("activity"));
private final Object mLock = new Object();
private final Binder mToken = new Binder();
@@ -275,6 +278,36 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
}
@Override
public void adoptShellPermissionIdentity(int uid) throws RemoteException {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
throwIfNotConnectedLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
mActivityManager.startDelegateShellPermissionIdentity(uid);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void dropShellPermissionIdentity() throws RemoteException {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
throwIfNotConnectedLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
mActivityManager.stopDelegateShellPermissionIdentity();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
public class Repeater implements Runnable {
// Continuously read readFrom and write back to writeTo until EOF is encountered
private final InputStream readFrom;

View File

@@ -3623,6 +3623,7 @@ public abstract class PackageManager {
*
* @hide
*/
@TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
public abstract void grantRuntimePermission(@NonNull String packageName,
@@ -3649,6 +3650,7 @@ public abstract class PackageManager {
*
* @hide
*/
@TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
public abstract void revokeRuntimePermission(@NonNull String packageName,

View File

@@ -29,9 +29,12 @@ import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.SparseArray;
import com.android.internal.util.function.TriFunction;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.function.BiFunction;
/**
* Package manager local system service interface.
@@ -64,6 +67,32 @@ public abstract class PackageManagerInternal {
void onPackageRemoved(@NonNull String packageName);
}
/** Interface to override permission checks via composition */
public interface CheckPermissionDelegate {
/**
* Allows overriding check permission behavior.
*
* @param permName The permission to check.
* @param pkgName The package for which to check.
* @param userId The user for which to check.
* @param superImpl The super implementation.
* @return The check permission result.
*/
int checkPermission(String permName, String pkgName, int userId,
TriFunction<String, String, Integer, Integer> superImpl);
/**
* Allows overriding check UID permission behavior.
*
* @param permName The permission to check.
* @param uid The UID for which to check.
* @param superImpl The super implementation.
* @return The check permission result.
*/
int checkUidPermission(String permName, int uid,
BiFunction<String, Integer, Integer> superImpl);
}
/**
* Provider for package names.
*/
@@ -633,4 +662,18 @@ public abstract class PackageManagerInternal {
* Ask the package manager to compile layouts in the given package.
*/
public abstract boolean compileLayouts(String packageName);
/**
* Get the delegate to influence permission checking.
*
* @return The delegate instance or null to clear.
*/
public abstract @Nullable CheckPermissionDelegate getCheckPermissionDelegate();
/**
* Set a delegate to influence permission checking.
*
* @param delegate A delegate instance or null to clear.
*/
public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate);
}

View File

@@ -33,7 +33,7 @@ interface IAppOpsService {
void stopWatchingMode(IAppOpsCallback callback);
IBinder getToken(IBinder clientToken);
int permissionToOpCode(String permission);
int noteProxyOperation(int code, String proxyPackageName,
int noteProxyOperation(int code, int proxyUid, String proxyPackageName,
int callingUid, String callingPackageName);
// Remaining methods are only used in Java.

View File

@@ -22,6 +22,7 @@ import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -207,6 +208,8 @@ public class AppOpsService extends IAppOpsService.Stub {
SparseIntArray mProfileOwners;
private CheckOpsDelegate mCheckOpsDelegate;
/**
* All times are in milliseconds. These constants are kept synchronized with the system
* global Settings. Any access to this class or its fields should be done while
@@ -1411,15 +1414,39 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
public CheckOpsDelegate getAppOpsServiceDelegate() {
synchronized (this) {
return mCheckOpsDelegate;
}
}
public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
synchronized (this) {
mCheckOpsDelegate = delegate;
}
}
@Override
public int checkOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
final CheckOpsDelegate delegate;
synchronized (this) {
if (mCheckOpsDelegate == null) {
return checkOperationImpl(code, uid, packageName);
}
delegate = mCheckOpsDelegate;
}
return delegate.checkOperation(code, uid, packageName,
AppOpsService.this::checkOperationImpl);
}
private int checkOperationImpl(int code, int uid, String packageName) {
synchronized (this) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
return AppOpsManager.MODE_IGNORED;
}
@@ -1439,20 +1466,33 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int checkAudioOperation(int code, int usage, int uid, String packageName) {
boolean suspended;
try {
suspended = isPackageSuspendedForUser(packageName, uid);
} catch (IllegalArgumentException ex) {
// Package not found.
suspended = false;
}
if (suspended) {
Slog.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid);
return AppOpsManager.MODE_IGNORED;
}
final CheckOpsDelegate delegate;
synchronized (this) {
if (mCheckOpsDelegate == null) {
return checkAudioOperationImpl(code, usage, uid, packageName);
}
delegate = mCheckOpsDelegate;
}
return delegate.checkAudioOperation(code, usage, uid, packageName,
AppOpsService.this::checkAudioOperationImpl);
}
private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
synchronized (this) {
boolean suspended;
try {
suspended = isPackageSuspendedForUser(packageName, uid);
} catch (IllegalArgumentException ex) {
// Package not found.
suspended = false;
}
if (suspended) {
Slog.i(TAG, "Audio disabled for suspended package=" + packageName
+ " for uid=" + uid);
return AppOpsManager.MODE_IGNORED;
}
final int mode = checkRestrictionLocked(code, usage, uid, packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
return mode;
@@ -1530,10 +1570,10 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override
public int noteProxyOperation(int code, String proxyPackageName,
int proxiedUid, String proxiedPackageName) {
public int noteProxyOperation(int code, int proxyUid,
String proxyPackageName, int proxiedUid, String proxiedPackageName) {
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
final int proxyUid = Binder.getCallingUid();
String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
if (resolveProxyPackageName == null) {
return AppOpsManager.MODE_IGNORED;
@@ -1553,6 +1593,18 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int noteOperation(int code, int uid, String packageName) {
final CheckOpsDelegate delegate;
synchronized (this) {
if (mCheckOpsDelegate == null) {
return noteOperationImpl(code, uid, packageName);
}
delegate = mCheckOpsDelegate;
}
return delegate.noteOperation(code, uid, packageName,
AppOpsService.this::noteOperationImpl);
}
private int noteOperationImpl(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);

View File

@@ -233,6 +233,7 @@ import android.app.ActivityThread;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.ApplicationErrorReport;
import android.app.ApplicationThreadConstants;
import android.app.BroadcastOptions;
@@ -296,6 +297,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
import android.content.pm.ParceledListSlice;
import android.content.pm.PathPermission;
import android.content.pm.PermissionInfo;
@@ -432,6 +434,8 @@ import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
@@ -516,6 +520,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -22177,6 +22182,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// Can't call out of the system process with a lock held, so post a message.
if (app.instr.mUiAutomationConnection != null) {
mAppOpsService.setAppOpsServiceDelegate(null);
getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
app.instr.mUiAutomationConnection).sendToTarget();
}
@@ -27189,4 +27196,143 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
}
@Override
public void startDelegateShellPermissionIdentity(int delegateUid) {
if (UserHandle.getCallingAppId() != Process.SHELL_UID
&& UserHandle.getCallingAppId() != Process.ROOT_UID) {
throw new SecurityException("Only the shell can delegate its permissions");
}
// We allow delegation only to one instrumentation started from the shell
synchronized (ActivityManagerService.this) {
// If there is a delegate it should be the same instance for app ops and permissions.
if (mAppOpsService.getAppOpsServiceDelegate()
!= getPackageManagerInternalLocked().getCheckPermissionDelegate()) {
throw new IllegalStateException("Bad shell delegate state");
}
// If the delegate is already set up for the target UID, nothing to do.
if (mAppOpsService.getAppOpsServiceDelegate() != null) {
if (!(mAppOpsService.getAppOpsServiceDelegate() instanceof ShellDelegate)) {
throw new IllegalStateException("Bad shell delegate state");
}
if (((ShellDelegate) mAppOpsService.getAppOpsServiceDelegate())
.getDelegateUid() != delegateUid) {
throw new SecurityException("Shell can delegate permissions only "
+ "to one instrumentation at a time");
}
return;
}
final int instrCount = mActiveInstrumentation.size();
for (int i = 0; i < instrCount; i++) {
final ActiveInstrumentation instr = mActiveInstrumentation.get(i);
if (instr.mTargetInfo.uid != delegateUid) {
continue;
}
// If instrumentation started from the shell the connection is not null
if (instr.mUiAutomationConnection == null) {
throw new SecurityException("Shell can delegate its permissions" +
" only to an instrumentation started from the shell");
}
// Hook them up...
final ShellDelegate shellDelegate = new ShellDelegate(
instr.mTargetInfo.packageName, delegateUid);
mAppOpsService.setAppOpsServiceDelegate(shellDelegate);
getPackageManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
return;
}
}
}
@Override
public void stopDelegateShellPermissionIdentity() {
if (UserHandle.getCallingAppId() != Process.SHELL_UID
&& UserHandle.getCallingAppId() != Process.ROOT_UID) {
throw new SecurityException("Only the shell can delegate its permissions");
}
synchronized (ActivityManagerService.this) {
mAppOpsService.setAppOpsServiceDelegate(null);
getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
}
}
private class ShellDelegate implements CheckOpsDelegate, CheckPermissionDelegate {
private final String mTargetPackageName;
private final int mTargetUid;
ShellDelegate(String targetPacakgeName, int targetUid) {
mTargetPackageName = targetPacakgeName;
mTargetUid = targetUid;
}
int getDelegateUid() {
return mTargetUid;
}
@Override
public int checkOperation(int code, int uid, String packageName,
TriFunction<Integer, Integer, String, Integer> superImpl) {
if (uid == mTargetUid) {
final long identity = Binder.clearCallingIdentity();
try {
return superImpl.apply(code, Process.SHELL_UID,
"com.android.shell");
} finally {
Binder.restoreCallingIdentity(identity);
}
}
return superImpl.apply(code, uid, packageName);
}
@Override
public int checkAudioOperation(int code, int usage, int uid, String packageName,
QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
if (uid == mTargetUid) {
final long identity = Binder.clearCallingIdentity();
try {
return superImpl.apply(code, usage, Process.SHELL_UID,
"com.android.shell");
} finally {
Binder.restoreCallingIdentity(identity);
}
}
return superImpl.apply(code, usage, uid, packageName);
}
@Override
public int noteOperation(int code, int uid, String packageName,
TriFunction<Integer, Integer, String, Integer> superImpl) {
if (uid == mTargetUid) {
final long identity = Binder.clearCallingIdentity();
try {
return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
"com.android.shell", uid, packageName);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
return superImpl.apply(code, uid, packageName);
}
@Override
public int checkPermission(String permName, String pkgName, int userId,
TriFunction<String, String, Integer, Integer> superImpl) {
if (mTargetPackageName.equals(pkgName)) {
return superImpl.apply(permName, "com.android.shell", userId);
}
return superImpl.apply(permName, pkgName, userId);
}
@Override
public int checkUidPermission(String permName, int uid,
BiFunction<String, Integer, Integer> superImpl) {
if (uid == mTargetUid) {
return superImpl.apply(permName, Process.SHELL_UID);
}
return superImpl.apply(permName, uid);
}
}
}

View File

@@ -177,6 +177,7 @@ import android.content.pm.PackageList;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
@@ -297,6 +298,8 @@ import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.TriFunction;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
@@ -376,6 +379,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Predicate;
/**
@@ -1043,6 +1047,9 @@ public class PackageManagerService extends IPackageManager.Stub
void receiveVerificationResponse(int verificationId);
}
@GuardedBy("mPackages")
private CheckPermissionDelegate mCheckPermissionDelegate;
private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> {
private Context mContext;
private ComponentName mIntentFilterVerifierComponent;
@@ -5352,11 +5359,35 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public int checkPermission(String permName, String pkgName, int userId) {
final CheckPermissionDelegate checkPermissionDelegate;
synchronized (mPackages) {
if (mCheckPermissionDelegate == null) {
return checkPermissionImpl(permName, pkgName, userId);
}
checkPermissionDelegate = mCheckPermissionDelegate;
}
return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
PackageManagerService.this::checkPermissionImpl);
}
private int checkPermissionImpl(String permName, String pkgName, int userId) {
return mPermissionManager.checkPermission(permName, pkgName, getCallingUid(), userId);
}
@Override
public int checkUidPermission(String permName, int uid) {
final CheckPermissionDelegate checkPermissionDelegate;
synchronized (mPackages) {
if (mCheckPermissionDelegate == null) {
return checkUidPermissionImpl(permName, uid);
}
checkPermissionDelegate = mCheckPermissionDelegate;
}
return checkPermissionDelegate.checkUidPermission(permName, uid,
PackageManagerService.this::checkUidPermissionImpl);
}
private int checkUidPermissionImpl(String permName, int uid) {
synchronized (mPackages) {
final String[] packageNames = getPackagesForUid(uid);
final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
@@ -9236,6 +9267,16 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
@GuardedBy("mPackages")
public CheckPermissionDelegate getCheckPermissionDelegateLocked() {
return mCheckPermissionDelegate;
}
@GuardedBy("mPackages")
public void setCheckPermissionDelegateLocked(CheckPermissionDelegate delegate) {
mCheckPermissionDelegate = delegate;
}
@GuardedBy("mPackages")
private void notifyPackageUseLocked(String packageName, int reason) {
final PackageParser.Package p = mPackages.get(packageName);
@@ -24515,6 +24556,20 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
return mArtManagerService.compileLayouts(pkg);
}
@Override
public CheckPermissionDelegate getCheckPermissionDelegate() {
synchronized (mPackages) {
return PackageManagerService.this.getCheckPermissionDelegateLocked();
}
}
@Override
public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
synchronized (mPackages) {
PackageManagerService.this.setCheckPermissionDelegateLocked(delegate);
}
}
}
@Override

View File

@@ -21,19 +21,11 @@ import android.annotation.Nullable;
import android.content.pm.PackageParser;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.PermissionInfoFlags;
import android.content.pm.PackageParser.Permission;
import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Internal interfaces to be used by other components within the system server.

View File

@@ -10,7 +10,9 @@ package android.test.mock {
method public String getPermissionControllerPackageName();
method @NonNull public String getServicesSystemSharedLibraryPackageName();
method @NonNull public String getSharedSystemSharedLibraryPackageName();
method public void grantRuntimePermission(String, String, android.os.UserHandle);
method public boolean isPermissionReviewModeEnabled();
method public void revokeRuntimePermission(String, String, android.os.UserHandle);
}
}