Merge "[MediaProjection] Secure aidl interfaces with permission checks"
This commit is contained in:
committed by
Android (Google) Code Review
commit
bfe03b9a2b
@@ -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);
|
||||
}
|
||||
|
||||
@@ -28,28 +28,34 @@ 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"
|
||||
+ ".permission.MANAGE_MEDIA_PROJECTION)")
|
||||
MediaProjectionInfo getActiveProjectionInfo();
|
||||
|
||||
@EnforcePermission("MANAGE_MEDIA_PROJECTION")
|
||||
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
|
||||
+ ".permission.MANAGE_MEDIA_PROJECTION)")
|
||||
void stopActiveProjection();
|
||||
|
||||
@EnforcePermission("MANAGE_MEDIA_PROJECTION")
|
||||
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
|
||||
+ ".permission.MANAGE_MEDIA_PROJECTION)")
|
||||
void notifyActiveProjectionCapturedContentResized(int width, int height);
|
||||
|
||||
@EnforcePermission("MANAGE_MEDIA_PROJECTION")
|
||||
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
|
||||
+ ".permission.MANAGE_MEDIA_PROJECTION)")
|
||||
void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible);
|
||||
@@ -70,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);
|
||||
}
|
||||
|
||||
@@ -11599,6 +11599,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");
|
||||
@@ -11608,6 +11609,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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -333,10 +339,13 @@ public final class MediaProjectionManagerService extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
|
||||
@Override // Binder call
|
||||
public void stopActiveProjection() {
|
||||
stopActiveProjection_enforcePermission();
|
||||
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to stop "
|
||||
+ "the active projection");
|
||||
}
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (mProjectionGrant != null) {
|
||||
@@ -347,10 +356,13 @@ public final class MediaProjectionManagerService extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
|
||||
@Override // Binder call
|
||||
public void notifyActiveProjectionCapturedContentResized(int width, int height) {
|
||||
notifyActiveProjectionCapturedContentResized_enforcePermission();
|
||||
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to notify "
|
||||
+ "on captured content resize");
|
||||
}
|
||||
if (!isCurrentProjection(mProjectionGrant)) {
|
||||
return;
|
||||
}
|
||||
@@ -364,10 +376,13 @@ public final class MediaProjectionManagerService extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
|
||||
@Override
|
||||
public void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible) {
|
||||
notifyActiveProjectionCapturedContentVisibilityChanged_enforcePermission();
|
||||
if (mContext.checkCallingOrSelfPermission(MANAGE_MEDIA_PROJECTION)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to notify "
|
||||
+ "on captured content visibility changed");
|
||||
}
|
||||
if (!isCurrentProjection(mProjectionGrant)) {
|
||||
return;
|
||||
}
|
||||
@@ -383,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");
|
||||
@@ -398,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");
|
||||
@@ -503,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
|
||||
@@ -651,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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user