Merge "[Media Projection] Require valid token to set session" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
55ecb4ec82
@@ -32,7 +32,6 @@ import android.graphics.Region;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IRemoteCallback;
|
import android.os.IRemoteCallback;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.view.ContentRecordingSession;
|
|
||||||
import android.view.DisplayCutout;
|
import android.view.DisplayCutout;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
import android.view.IAppTransitionAnimationSpecsFuture;
|
import android.view.IAppTransitionAnimationSpecsFuture;
|
||||||
@@ -873,17 +872,6 @@ interface IWindowManager
|
|||||||
*/
|
*/
|
||||||
void detachWindowContextFromWindowContainer(IBinder clientToken);
|
void detachWindowContextFromWindowContainer(IBinder clientToken);
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the content recording session. If a different session is already in progress, then
|
|
||||||
* the pre-existing session is stopped, and the new incoming session takes over.
|
|
||||||
*
|
|
||||||
* The DisplayContent for the new session will begin recording when
|
|
||||||
* {@link RootWindowContainer#onDisplayChanged} is invoked for the new {@link VirtualDisplay}.
|
|
||||||
*
|
|
||||||
* @param incomingSession the nullable incoming content recording session
|
|
||||||
*/
|
|
||||||
void setContentRecordingSession(in ContentRecordingSession incomingSession);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a listener, which is to be called whenever cross-window blur is enabled/disabled.
|
* Registers a listener, which is to be called whenever cross-window blur is enabled/disabled.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import android.media.projection.IMediaProjectionCallback;
|
|||||||
import android.media.projection.IMediaProjectionWatcherCallback;
|
import android.media.projection.IMediaProjectionWatcherCallback;
|
||||||
import android.media.projection.MediaProjectionInfo;
|
import android.media.projection.MediaProjectionInfo;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.view.ContentRecordingSession;
|
||||||
|
|
||||||
/** {@hide} */
|
/** {@hide} */
|
||||||
interface IMediaProjectionManager {
|
interface IMediaProjectionManager {
|
||||||
@@ -33,4 +34,15 @@ interface IMediaProjectionManager {
|
|||||||
void stopActiveProjection();
|
void stopActiveProjection();
|
||||||
void addCallback(IMediaProjectionWatcherCallback callback);
|
void addCallback(IMediaProjectionWatcherCallback callback);
|
||||||
void removeCallback(IMediaProjectionWatcherCallback callback);
|
void removeCallback(IMediaProjectionWatcherCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the content recording session. If a different session is already in progress, then
|
||||||
|
* the pre-existing session is stopped, and the new incoming session takes over. Only updates
|
||||||
|
* the session if the given projection is valid.
|
||||||
|
*
|
||||||
|
* @param incomingSession the nullable incoming content recording session
|
||||||
|
* @param projection the non-null projection the session describes
|
||||||
|
*/
|
||||||
|
void setContentRecordingSession(in ContentRecordingSession incomingSession,
|
||||||
|
in IMediaProjection projection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,11 @@ import android.hardware.display.VirtualDisplay;
|
|||||||
import android.hardware.display.VirtualDisplayConfig;
|
import android.hardware.display.VirtualDisplayConfig;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContentRecordingSession;
|
import android.view.ContentRecordingSession;
|
||||||
import android.view.IWindowManager;
|
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.WindowManagerGlobal;
|
|
||||||
import android.window.WindowContainerToken;
|
import android.window.WindowContainerToken;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -53,6 +52,7 @@ public final class MediaProjection {
|
|||||||
private final IMediaProjection mImpl;
|
private final IMediaProjection mImpl;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final Map<Callback, CallbackRecord> mCallbacks;
|
private final Map<Callback, CallbackRecord> mCallbacks;
|
||||||
|
@Nullable private IMediaProjectionManager mProjectionService = null;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public MediaProjection(Context context, IMediaProjection impl) {
|
public MediaProjection(Context context, IMediaProjection impl) {
|
||||||
@@ -172,7 +172,6 @@ public final class MediaProjection {
|
|||||||
@NonNull VirtualDisplayConfig.Builder virtualDisplayConfig,
|
@NonNull VirtualDisplayConfig.Builder virtualDisplayConfig,
|
||||||
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
|
||||||
try {
|
try {
|
||||||
final IWindowManager wmService = WindowManagerGlobal.getWindowManagerService();
|
|
||||||
final WindowContainerToken taskWindowContainerToken =
|
final WindowContainerToken taskWindowContainerToken =
|
||||||
mImpl.getTaskRecordingWindowContainerToken();
|
mImpl.getTaskRecordingWindowContainerToken();
|
||||||
Context windowContext = null;
|
Context windowContext = null;
|
||||||
@@ -199,7 +198,7 @@ public final class MediaProjection {
|
|||||||
}
|
}
|
||||||
session.setDisplayId(virtualDisplay.getDisplay().getDisplayId());
|
session.setDisplayId(virtualDisplay.getDisplay().getDisplayId());
|
||||||
// Successfully set up, so save the current session details.
|
// Successfully set up, so save the current session details.
|
||||||
wmService.setContentRecordingSession(session);
|
getProjectionService().setContentRecordingSession(session, mImpl);
|
||||||
return virtualDisplay;
|
return virtualDisplay;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Can not capture if WMS is not accessible, so bail out.
|
// Can not capture if WMS is not accessible, so bail out.
|
||||||
@@ -207,6 +206,14 @@ public final class MediaProjection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IMediaProjectionManager getProjectionService() {
|
||||||
|
if (mProjectionService == null) {
|
||||||
|
mProjectionService = IMediaProjectionManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE));
|
||||||
|
}
|
||||||
|
return mProjectionService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops projection.
|
* Stops projection.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -45,14 +45,15 @@ import android.os.RemoteException;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.view.ContentRecordingSession;
|
||||||
import android.window.WindowContainerToken;
|
import android.window.WindowContainerToken;
|
||||||
|
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.DumpUtils;
|
import com.android.internal.util.DumpUtils;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
import com.android.server.SystemService.TargetUser;
|
|
||||||
import com.android.server.Watchdog;
|
import com.android.server.Watchdog;
|
||||||
|
import com.android.server.wm.WindowManagerInternal;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -381,6 +382,27 @@ public final class MediaProjectionManagerService extends SystemService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current content mirroring session.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setContentRecordingSession(@Nullable ContentRecordingSession incomingSession,
|
||||||
|
@NonNull IMediaProjection projection) {
|
||||||
|
final long origId = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (!isValidMediaProjection(projection)) {
|
||||||
|
throw new SecurityException("Invalid media projection");
|
||||||
|
}
|
||||||
|
LocalServices.getService(
|
||||||
|
WindowManagerInternal.class).setContentRecordingSession(
|
||||||
|
incomingSession);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(origId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override // Binder call
|
@Override // Binder call
|
||||||
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
|
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
|
||||||
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
|
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ final class ContentRecorder {
|
|||||||
// Update the cached session state first, since updating the service will result in always
|
// Update the cached session state first, since updating the service will result in always
|
||||||
// returning to this instance to update recording state.
|
// returning to this instance to update recording state.
|
||||||
mContentRecordingSession = null;
|
mContentRecordingSession = null;
|
||||||
mDisplayContent.mWmService.setContentRecordingSession(null);
|
mDisplayContent.mWmService.mContentRecordingController.setContentRecordingSessionLocked(
|
||||||
|
null, mDisplayContent.mWmService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import android.hardware.display.DisplayManagerInternal;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
import android.view.ContentRecordingSession;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.IInputFilter;
|
import android.view.IInputFilter;
|
||||||
import android.view.IRemoteAnimationFinishedCallback;
|
import android.view.IRemoteAnimationFinishedCallback;
|
||||||
@@ -869,4 +870,16 @@ public abstract class WindowManagerInternal {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean isPointInsideWindow(
|
public abstract boolean isPointInsideWindow(
|
||||||
@NonNull IBinder windowToken, int displayId, float displayX, float displayY);
|
@NonNull IBinder windowToken, int displayId, float displayX, float displayY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the content recording session. If a different session is already in progress, then
|
||||||
|
* the pre-existing session is stopped, and the new incoming session takes over.
|
||||||
|
*
|
||||||
|
* The DisplayContent for the new session will begin recording when
|
||||||
|
* {@link RootWindowContainer#onDisplayChanged} is invoked for the new {@link VirtualDisplay}.
|
||||||
|
* Must be invoked for a valid MediaProjection session.
|
||||||
|
*
|
||||||
|
* @param incomingSession the nullable incoming content recording session
|
||||||
|
*/
|
||||||
|
public abstract void setContentRecordingSession(ContentRecordingSession incomingSession);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2956,16 +2956,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the current content mirroring session.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setContentRecordingSession(@Nullable ContentRecordingSession incomingSession) {
|
|
||||||
synchronized (mGlobalLock) {
|
|
||||||
mContentRecordingController.setContentRecordingSessionLocked(incomingSession, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(multi-display): remove when no default display use case.
|
// TODO(multi-display): remove when no default display use case.
|
||||||
void prepareAppTransitionNone() {
|
void prepareAppTransitionNone() {
|
||||||
if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
|
if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
|
||||||
@@ -8242,6 +8232,14 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
return w.getBounds().contains((int) displayX, (int) displayY);
|
return w.getBounds().contains((int) displayX, (int) displayY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContentRecordingSession(@Nullable ContentRecordingSession incomingSession) {
|
||||||
|
synchronized (mGlobalLock) {
|
||||||
|
mContentRecordingController.setContentRecordingSessionLocked(incomingSession,
|
||||||
|
WindowManagerService.this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerAppFreezeListener(AppFreezeListener listener) {
|
void registerAppFreezeListener(AppFreezeListener listener) {
|
||||||
|
|||||||
@@ -2441,7 +2441,7 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
|
ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
|
||||||
tokenToMirror);
|
tokenToMirror);
|
||||||
session.setDisplayId(displayId);
|
session.setDisplayId(displayId);
|
||||||
mWm.setContentRecordingSession(session);
|
mWm.mContentRecordingController.setContentRecordingSessionLocked(session, mWm);
|
||||||
actualDC.updateRecording();
|
actualDC.updateRecording();
|
||||||
|
|
||||||
// THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off.
|
// THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off.
|
||||||
@@ -2470,7 +2470,7 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
|
ContentRecordingSession session = ContentRecordingSession.createDisplaySession(
|
||||||
tokenToMirror);
|
tokenToMirror);
|
||||||
session.setDisplayId(displayId);
|
session.setDisplayId(displayId);
|
||||||
mWm.setContentRecordingSession(session);
|
mWm.mContentRecordingController.setContentRecordingSessionLocked(session, mWm);
|
||||||
mWm.mRoot.onDisplayAdded(displayId);
|
mWm.mRoot.onDisplayAdded(displayId);
|
||||||
|
|
||||||
// WHEN getting the DisplayContent for the new virtual display.
|
// WHEN getting the DisplayContent for the new virtual display.
|
||||||
|
|||||||
Reference in New Issue
Block a user