Merge "[MediaProjection] Secure aidl interfaces with permission checks" into udc-dev

This commit is contained in:
TreeHugger Robot
2023-03-29 19:33:19 +00:00
committed by Android (Google) Code Review
5 changed files with 62 additions and 14 deletions

View File

@@ -23,22 +23,32 @@ import android.os.IBinder;
interface IMediaProjection {
void start(IMediaProjectionCallback callback);
void stop();
boolean canProjectAudio();
boolean canProjectVideo();
boolean canProjectSecureVideo();
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
int applyVirtualDisplayFlags(int flags);
void registerCallback(IMediaProjectionCallback callback);
void unregisterCallback(IMediaProjectionCallback callback);
/**
* Returns the {@link android.os.IBinder} identifying the task to record, or {@code null} if
* there is none.
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
IBinder getLaunchCookie();
/**
* Updates the {@link android.os.IBinder} identifying the task to record, or {@code null} if
* there is none.
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
void setLaunchCookie(in IBinder launchCookie);
}

View File

@@ -28,11 +28,20 @@ interface IMediaProjectionManager {
@UnsupportedAppUsage
boolean hasProjectionPermission(int uid, String packageName);
/**
* Returns a new {@link IMediaProjection} instance associated with the given package.
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
IMediaProjection createProjection(int uid, String packageName, int type,
boolean permanentGrant);
/**
* Returns {@code true} if the given {@link IMediaProjection} corresponds to the current
* projection, or {@code false} otherwise.
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
boolean isCurrentProjection(IMediaProjection projection);
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
@@ -67,6 +76,8 @@ interface IMediaProjectionManager {
* @param incomingSession the nullable incoming content recording session
* @param projection the non-null projection the session describes
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
void setContentRecordingSession(in ContentRecordingSession incomingSession,
in IMediaProjection projection);
}

View File

@@ -11602,6 +11602,7 @@ public class AudioService extends IAudioService.Stub
return false;
}
final long token = Binder.clearCallingIdentity();
try {
if (!projectionService.isCurrentProjection(projection)) {
Log.w(TAG, "App passed invalid MediaProjection token");
@@ -11611,6 +11612,8 @@ public class AudioService extends IAudioService.Stub
Log.e(TAG, "Can't call .isCurrentProjection() on IMediaProjectionManager"
+ projectionService.asBinder(), e);
return false;
} finally {
Binder.restoreCallingIdentity(token);
}
try {

View File

@@ -1419,6 +1419,7 @@ public final class DisplayManagerService extends SystemService {
}
if (projection != null) {
final long firstToken = Binder.clearCallingIdentity();
try {
if (!getProjectionService().isCurrentProjection(projection)) {
throw new SecurityException("Cannot create VirtualDisplay with "
@@ -1427,6 +1428,8 @@ public final class DisplayManagerService extends SystemService {
flags = projection.applyVirtualDisplayFlags(flags);
} catch (RemoteException e) {
throw new SecurityException("unable to validate media projection or flags");
} finally {
Binder.restoreCallingIdentity(firstToken);
}
}
@@ -1494,7 +1497,7 @@ public final class DisplayManagerService extends SystemService {
throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
}
final long token = Binder.clearCallingIdentity();
final long secondToken = Binder.clearCallingIdentity();
try {
final int displayId;
synchronized (mSyncRoot) {
@@ -1566,7 +1569,7 @@ public final class DisplayManagerService extends SystemService {
return displayId;
} finally {
Binder.restoreCallingIdentity(token);
Binder.restoreCallingIdentity(secondToken);
}
}

View File

@@ -16,6 +16,7 @@
package com.android.server.media.projection;
import static android.Manifest.permission.MANAGE_MEDIA_PROJECTION;
import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_CREATED;
import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED;
@@ -282,7 +283,7 @@ public final class MediaProjectionManagerService extends SystemService
@Override // Binder call
public IMediaProjection createProjection(int uid, String packageName, int type,
boolean isPermanentGrant) {
if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to grant "
+ "projection permission");
@@ -314,16 +315,21 @@ public final class MediaProjectionManagerService extends SystemService
@Override // Binder call
public boolean isCurrentProjection(IMediaProjection projection) {
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to check "
+ "if the given projection is current.");
}
return MediaProjectionManagerService.this.isCurrentProjection(
projection == null ? null : projection.asBinder());
}
@Override // Binder call
public MediaProjectionInfo getActiveProjectionInfo() {
if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+ "projection callbacks");
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to get "
+ "active projection info");
}
final long token = Binder.clearCallingIdentity();
try {
@@ -335,10 +341,10 @@ public final class MediaProjectionManagerService extends SystemService
@Override // Binder call
public void stopActiveProjection() {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+ "projection callbacks");
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to stop "
+ "the active projection");
}
final long token = Binder.clearCallingIdentity();
try {
@@ -352,7 +358,7 @@ public final class MediaProjectionManagerService extends SystemService
@Override // Binder call
public void notifyActiveProjectionCapturedContentResized(int width, int height) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to notify "
+ "on captured content resize");
@@ -372,10 +378,10 @@ public final class MediaProjectionManagerService extends SystemService
@Override
public void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to notify "
+ "on captured content resize");
+ "on captured content visibility changed");
}
if (!isCurrentProjection(mProjectionGrant)) {
return;
@@ -392,7 +398,7 @@ public final class MediaProjectionManagerService extends SystemService
@Override //Binder call
public void addCallback(final IMediaProjectionWatcherCallback callback) {
if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+ "projection callbacks");
@@ -407,7 +413,7 @@ public final class MediaProjectionManagerService extends SystemService
@Override
public void removeCallback(IMediaProjectionWatcherCallback callback) {
if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
if (mContext.checkCallingPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to remove "
+ "projection callbacks");
@@ -512,6 +518,11 @@ public final class MediaProjectionManagerService extends SystemService
@Override // Binder call
public int applyVirtualDisplayFlags(int flags) {
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to apply virtual "
+ "display flags.");
}
if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) {
flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
@@ -660,11 +671,21 @@ public final class MediaProjectionManagerService extends SystemService
@Override // Binder call
public void setLaunchCookie(IBinder launchCookie) {
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to set launch "
+ "cookie.");
}
mLaunchCookie = launchCookie;
}
@Override // Binder call
public IBinder getLaunchCookie() {
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to get launch "
+ "cookie.");
}
return mLaunchCookie;
}