This repository has been archived by the owner on Nov 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce SystemAPI MediaProjectionGlobal
This API can be used from calls outside applications to create a virtual display for mirroring. The permission checks in system server are still in place so the caller must have CAPTURE_VIDEO_OUTPUT permission. This class is intented to be used by systems that to stream device content, but not from an application. In most cases, this will be called from Shell or a system application. Test: MediaProjectGlobalTest Bug: 237664947 Change-Id: I43f79c83db7c82c0b682ef174fb1a5ab83795489
- Loading branch information
Chavi Weingarten
committed
Sep 16, 2022
1 parent
4653017
commit 612711c
Showing
4 changed files
with
135 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
media/java/android/media/projection/MediaProjectionGlobal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* Copyright (C) 2022 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package android.media.projection; | ||
|
||
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; | ||
|
||
import android.annotation.NonNull; | ||
import android.annotation.Nullable; | ||
import android.annotation.SystemApi; | ||
import android.content.Context; | ||
import android.content.pm.IPackageManager; | ||
import android.hardware.display.DisplayManagerGlobal; | ||
import android.hardware.display.IDisplayManager; | ||
import android.hardware.display.VirtualDisplay; | ||
import android.hardware.display.VirtualDisplayConfig; | ||
import android.os.IBinder; | ||
import android.os.Process; | ||
import android.os.RemoteException; | ||
import android.os.ServiceManager; | ||
import android.view.Surface; | ||
|
||
/** | ||
* This is a helper for MediaProjection when requests are made from outside an application. This | ||
* should only be used by processes running as shell as a way to capture recordings without being | ||
* an application. The requests will fail if coming from any process that's not Shell. | ||
* @hide | ||
*/ | ||
@SystemApi | ||
public class MediaProjectionGlobal { | ||
private static final Object sLock = new Object(); | ||
private static MediaProjectionGlobal sInstance; | ||
|
||
/** | ||
* @return The instance of {@link MediaProjectionGlobal} | ||
*/ | ||
@NonNull | ||
public static MediaProjectionGlobal getInstance() { | ||
synchronized (sLock) { | ||
if (sInstance == null) { | ||
final IBinder displayBinder = ServiceManager.getService(Context.DISPLAY_SERVICE); | ||
final IBinder packageBinder = ServiceManager.getService("package"); | ||
if (displayBinder != null && packageBinder != null) { | ||
sInstance = new MediaProjectionGlobal( | ||
IDisplayManager.Stub.asInterface(displayBinder), | ||
IPackageManager.Stub.asInterface(packageBinder)); | ||
} | ||
} | ||
return sInstance; | ||
} | ||
} | ||
|
||
private final IDisplayManager mDm; | ||
private final IPackageManager mPackageManager; | ||
|
||
private MediaProjectionGlobal(IDisplayManager dm, IPackageManager packageManager) { | ||
mDm = dm; | ||
mPackageManager = packageManager; | ||
} | ||
|
||
/** | ||
* Creates a VirtualDisplay that will mirror the content of displayIdToMirror | ||
* @param name The name for the virtual display | ||
* @param width The initial width for the virtual display | ||
* @param height The initial height for the virtual display | ||
* @param displayIdToMirror The displayId that will be mirrored into the virtual display. | ||
* @return VirtualDisplay that can be used to update properties. | ||
*/ | ||
@Nullable | ||
public VirtualDisplay createVirtualDisplay(@NonNull String name, int width, int height, | ||
int displayIdToMirror, @Nullable Surface surface) { | ||
|
||
// Density doesn't matter since this virtual display is only used for mirroring. | ||
VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, | ||
height, 1 /* densityDpi */) | ||
.setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) | ||
.setDisplayIdToMirror(displayIdToMirror); | ||
if (surface != null) { | ||
builder.setSurface(surface); | ||
} | ||
VirtualDisplayConfig virtualDisplayConfig = builder.build(); | ||
|
||
String[] packages; | ||
try { | ||
packages = mPackageManager.getPackagesForUid(Process.myUid()); | ||
} catch (RemoteException ex) { | ||
throw ex.rethrowFromSystemServer(); | ||
} | ||
|
||
// Just use the first one since it just needs to match the package when looking it up by | ||
// calling UID in system server. | ||
// The call may come from a rooted device, in that case the requesting uid will be root so | ||
// it will not have any package name | ||
String packageName = packages == null ? null : packages[0]; | ||
DisplayManagerGlobal.VirtualDisplayCallback | ||
callbackWrapper = new DisplayManagerGlobal.VirtualDisplayCallback(null, null); | ||
int displayId; | ||
try { | ||
displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper, null, | ||
packageName); | ||
} catch (RemoteException ex) { | ||
throw ex.rethrowFromSystemServer(); | ||
} | ||
return DisplayManagerGlobal.getInstance().createVirtualDisplayWrapper(virtualDisplayConfig, | ||
null, callbackWrapper, displayId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters