Merge "Add auto-grant permission slice API" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-03-30 18:45:00 +00:00
committed by Android (Google) Code Review
6 changed files with 65 additions and 7 deletions

View File

@@ -7304,6 +7304,7 @@ package android.app.slice {
}
public abstract class SliceProvider extends android.content.ContentProvider {
ctor public SliceProvider(java.lang.String...);
ctor public SliceProvider();
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
method public final java.lang.String getType(android.net.Uri);

View File

@@ -25,7 +25,8 @@ interface ISliceManager {
void unpinSlice(String pkg, in Uri uri, in IBinder token);
boolean hasSliceAccess(String pkg);
SliceSpec[] getPinnedSpecs(in Uri uri, String pkg);
int checkSlicePermission(in Uri uri, String pkg, int pid, int uid);
int checkSlicePermission(in Uri uri, String pkg, int pid, int uid,
in String[] autoGrantPermissions);
void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices);
Uri[] getPinnedSlices(String pkg);

View File

@@ -404,7 +404,8 @@ public class SliceManager {
* Does the permission check to see if a caller has access to a specific slice.
* @hide
*/
public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid) {
public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid,
String[] autoGrantPermissions) {
try {
if (UserHandle.isSameApp(uid, Process.myUid())) {
return;
@@ -412,7 +413,7 @@ public class SliceManager {
if (pkg == null) {
throw new SecurityException("No pkg specified");
}
int result = mService.checkSlicePermission(uri, pkg, pid, uid);
int result = mService.checkSlicePermission(uri, pkg, pid, uid, autoGrantPermissions);
if (result == PERMISSION_DENIED) {
throw new SecurityException("User " + uid + " does not have slice permission for "
+ uri + ".");
@@ -424,6 +425,8 @@ public class SliceManager {
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
// Notify a change has happened because we just granted a permission.
mContext.getContentResolver().notifyChange(uri, null);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();

View File

@@ -149,10 +149,31 @@ public abstract class SliceProvider extends ContentProvider {
private static final boolean DEBUG = false;
private static final long SLICE_BIND_ANR = 2000;
private final String[] mAutoGrantPermissions;
private String mCallback;
private SliceManager mSliceManager;
/**
* A version of constructing a SliceProvider that allows autogranting slice permissions
* to apps that hold specific platform permissions.
* <p>
* When an app tries to bind a slice from this provider that it does not have access to,
* This provider will check if the caller holds permissions to any of the autoGrantPermissions
* specified, if they do they will be granted persisted uri access to all slices of this
* provider.
*
* @param autoGrantPermissions List of permissions that holders are auto-granted access
* to slices.
*/
public SliceProvider(@NonNull String... autoGrantPermissions) {
mAutoGrantPermissions = autoGrantPermissions;
}
public SliceProvider() {
mAutoGrantPermissions = new String[0];
}
@Override
public void attachInfo(Context context, ProviderInfo info) {
super.attachInfo(context, info);
@@ -402,7 +423,7 @@ public abstract class SliceProvider extends ContentProvider {
: getContext().getPackageManager().getNameForUid(callingUid);
try {
mSliceManager.enforceSlicePermission(sliceUri, pkg,
callingPid, callingUid);
callingPid, callingUid, mAutoGrantPermissions);
} catch (SecurityException e) {
return createPermissionSlice(getContext(), sliceUri, pkg);
}

View File

@@ -168,7 +168,8 @@ public class SliceManagerService extends ISliceManager.Stub {
}
@Override
public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token) throws RemoteException {
public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token)
throws RemoteException {
verifyCaller(pkg);
enforceAccess(pkg, uri);
int user = Binder.getCallingUserHandle().getIdentifier();
@@ -210,7 +211,8 @@ public class SliceManagerService extends ISliceManager.Stub {
}
@Override
public int checkSlicePermission(Uri uri, String pkg, int pid, int uid) throws RemoteException {
public int checkSlicePermission(Uri uri, String pkg, int pid, int uid,
String[] autoGrantPermissions) throws RemoteException {
if (mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
== PERMISSION_GRANTED) {
return SliceManager.PERMISSION_GRANTED;
@@ -218,6 +220,11 @@ public class SliceManagerService extends ISliceManager.Stub {
if (hasFullSliceAccess(pkg, UserHandle.getUserId(uid))) {
return SliceManager.PERMISSION_GRANTED;
}
for (String perm : autoGrantPermissions) {
if (mContext.checkPermission(perm, pid, uid) == PERMISSION_GRANTED) {
return SliceManager.PERMISSION_USER_GRANTED;
}
}
synchronized (mLock) {
if (mUserGrants.contains(new SliceGrant(uri, pkg, UserHandle.getUserId(uid)))) {
return SliceManager.PERMISSION_USER_GRANTED;

View File

@@ -15,8 +15,10 @@
package com.android.server.slice;
import static android.content.ContentProvider.maybeAddUserId;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -35,9 +37,11 @@ import android.content.pm.PackageManagerInternal;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -63,6 +67,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
private SliceManagerService mService;
private PinnedSliceState mCreatedSliceState;
private IBinder mToken = new Binder();
private TestableContext mContextSpy;
@Before
public void setup() {
@@ -72,7 +77,8 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
mContext.getTestablePermissions().setPermission(TEST_URI, PERMISSION_GRANTED);
mService = spy(new SliceManagerService(mContext, TestableLooper.get(this).getLooper()));
mContextSpy = spy(mContext);
mService = spy(new SliceManagerService(mContextSpy, TestableLooper.get(this).getLooper()));
mCreatedSliceState = mock(PinnedSliceState.class);
doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString());
}
@@ -103,4 +109,23 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
verify(mCreatedSliceState, never()).destroy();
}
@Test
public void testCheckAutoGrantPermissions() throws RemoteException {
String[] testPerms = new String[] {
"perm1",
"perm2",
};
when(mContextSpy.checkUriPermission(any(), anyInt(), anyInt(), anyInt()))
.thenReturn(PERMISSION_DENIED);
when(mContextSpy.checkPermission("perm1", Process.myPid(), Process.myUid()))
.thenReturn(PERMISSION_DENIED);
when(mContextSpy.checkPermission("perm2", Process.myPid(), Process.myUid()))
.thenReturn(PERMISSION_GRANTED);
mService.checkSlicePermission(TEST_URI, mContext.getPackageName(), Process.myPid(),
Process.myUid(), testPerms);
verify(mContextSpy).checkPermission(eq("perm1"), eq(Process.myPid()), eq(Process.myUid()));
verify(mContextSpy).checkPermission(eq("perm2"), eq(Process.myPid()), eq(Process.myUid()));
}
}