Merge "Add auto-grant permission slice API" into pi-dev
am: 4ced90cb12
Change-Id: I1cafb654553e62e8720d6c8b101328d5227dc545
This commit is contained in:
@@ -7304,6 +7304,7 @@ package android.app.slice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SliceProvider extends android.content.ContentProvider {
|
public abstract class SliceProvider extends android.content.ContentProvider {
|
||||||
|
ctor public SliceProvider(java.lang.String...);
|
||||||
ctor public SliceProvider();
|
ctor public SliceProvider();
|
||||||
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
|
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
|
||||||
method public final java.lang.String getType(android.net.Uri);
|
method public final java.lang.String getType(android.net.Uri);
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ interface ISliceManager {
|
|||||||
void unpinSlice(String pkg, in Uri uri, in IBinder token);
|
void unpinSlice(String pkg, in Uri uri, in IBinder token);
|
||||||
boolean hasSliceAccess(String pkg);
|
boolean hasSliceAccess(String pkg);
|
||||||
SliceSpec[] getPinnedSpecs(in Uri uri, 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);
|
void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices);
|
||||||
Uri[] getPinnedSlices(String pkg);
|
Uri[] getPinnedSlices(String pkg);
|
||||||
|
|
||||||
|
|||||||
@@ -404,7 +404,8 @@ public class SliceManager {
|
|||||||
* Does the permission check to see if a caller has access to a specific slice.
|
* Does the permission check to see if a caller has access to a specific slice.
|
||||||
* @hide
|
* @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 {
|
try {
|
||||||
if (UserHandle.isSameApp(uid, Process.myUid())) {
|
if (UserHandle.isSameApp(uid, Process.myUid())) {
|
||||||
return;
|
return;
|
||||||
@@ -412,7 +413,7 @@ public class SliceManager {
|
|||||||
if (pkg == null) {
|
if (pkg == null) {
|
||||||
throw new SecurityException("No pkg specified");
|
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) {
|
if (result == PERMISSION_DENIED) {
|
||||||
throw new SecurityException("User " + uid + " does not have slice permission for "
|
throw new SecurityException("User " + uid + " does not have slice permission for "
|
||||||
+ uri + ".");
|
+ uri + ".");
|
||||||
@@ -424,6 +425,8 @@ public class SliceManager {
|
|||||||
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
| Intent.FLAG_GRANT_PREFIX_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) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
|
|||||||
@@ -149,10 +149,31 @@ public abstract class SliceProvider extends ContentProvider {
|
|||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private static final long SLICE_BIND_ANR = 2000;
|
private static final long SLICE_BIND_ANR = 2000;
|
||||||
|
private final String[] mAutoGrantPermissions;
|
||||||
|
|
||||||
private String mCallback;
|
private String mCallback;
|
||||||
private SliceManager mSliceManager;
|
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
|
@Override
|
||||||
public void attachInfo(Context context, ProviderInfo info) {
|
public void attachInfo(Context context, ProviderInfo info) {
|
||||||
super.attachInfo(context, info);
|
super.attachInfo(context, info);
|
||||||
@@ -402,7 +423,7 @@ public abstract class SliceProvider extends ContentProvider {
|
|||||||
: getContext().getPackageManager().getNameForUid(callingUid);
|
: getContext().getPackageManager().getNameForUid(callingUid);
|
||||||
try {
|
try {
|
||||||
mSliceManager.enforceSlicePermission(sliceUri, pkg,
|
mSliceManager.enforceSlicePermission(sliceUri, pkg,
|
||||||
callingPid, callingUid);
|
callingPid, callingUid, mAutoGrantPermissions);
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
return createPermissionSlice(getContext(), sliceUri, pkg);
|
return createPermissionSlice(getContext(), sliceUri, pkg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,8 @@ public class SliceManagerService extends ISliceManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
verifyCaller(pkg);
|
||||||
enforceAccess(pkg, uri);
|
enforceAccess(pkg, uri);
|
||||||
int user = Binder.getCallingUserHandle().getIdentifier();
|
int user = Binder.getCallingUserHandle().getIdentifier();
|
||||||
@@ -210,7 +211,8 @@ public class SliceManagerService extends ISliceManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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)
|
if (mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
== PERMISSION_GRANTED) {
|
== PERMISSION_GRANTED) {
|
||||||
return SliceManager.PERMISSION_GRANTED;
|
return SliceManager.PERMISSION_GRANTED;
|
||||||
@@ -218,6 +220,11 @@ public class SliceManagerService extends ISliceManager.Stub {
|
|||||||
if (hasFullSliceAccess(pkg, UserHandle.getUserId(uid))) {
|
if (hasFullSliceAccess(pkg, UserHandle.getUserId(uid))) {
|
||||||
return SliceManager.PERMISSION_GRANTED;
|
return SliceManager.PERMISSION_GRANTED;
|
||||||
}
|
}
|
||||||
|
for (String perm : autoGrantPermissions) {
|
||||||
|
if (mContext.checkPermission(perm, pid, uid) == PERMISSION_GRANTED) {
|
||||||
|
return SliceManager.PERMISSION_USER_GRANTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mUserGrants.contains(new SliceGrant(uri, pkg, UserHandle.getUserId(uid)))) {
|
if (mUserGrants.contains(new SliceGrant(uri, pkg, UserHandle.getUserId(uid)))) {
|
||||||
return SliceManager.PERMISSION_USER_GRANTED;
|
return SliceManager.PERMISSION_USER_GRANTED;
|
||||||
|
|||||||
@@ -15,8 +15,10 @@
|
|||||||
package com.android.server.slice;
|
package com.android.server.slice;
|
||||||
|
|
||||||
import static android.content.ContentProvider.maybeAddUserId;
|
import static android.content.ContentProvider.maybeAddUserId;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
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.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
@@ -35,9 +37,11 @@ import android.content.pm.PackageManagerInternal;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableContext;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
import android.testing.TestableLooper.RunWithLooper;
|
import android.testing.TestableLooper.RunWithLooper;
|
||||||
|
|
||||||
@@ -63,6 +67,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
|
|||||||
private SliceManagerService mService;
|
private SliceManagerService mService;
|
||||||
private PinnedSliceState mCreatedSliceState;
|
private PinnedSliceState mCreatedSliceState;
|
||||||
private IBinder mToken = new Binder();
|
private IBinder mToken = new Binder();
|
||||||
|
private TestableContext mContextSpy;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@@ -72,7 +77,8 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
|
|||||||
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
|
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
|
||||||
mContext.getTestablePermissions().setPermission(TEST_URI, PERMISSION_GRANTED);
|
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);
|
mCreatedSliceState = mock(PinnedSliceState.class);
|
||||||
doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString());
|
doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString());
|
||||||
}
|
}
|
||||||
@@ -103,4 +109,23 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
|
|||||||
verify(mCreatedSliceState, never()).destroy();
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user