Create VirtualDeviceManager

CTS-Coverage-Bug: 194949534
Bug: 194949534
Test: ag/15781910
Change-Id: I06d245d91827390de99b9ff3e514af4294a11476
This commit is contained in:
Maurice Lam
2021-08-04 20:23:41 -07:00
parent bbd05d765e
commit 771c72a607
9 changed files with 306 additions and 0 deletions

View File

@@ -95,6 +95,7 @@ package android {
field public static final String CONTROL_OEM_PAID_NETWORK_PREFERENCE = "android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE";
field public static final String CONTROL_VPN = "android.permission.CONTROL_VPN";
field public static final String CREATE_USERS = "android.permission.CREATE_USERS";
field public static final String CREATE_VIRTUAL_DEVICE = "android.permission.CREATE_VIRTUAL_DEVICE";
field public static final String CRYPT_KEEPER = "android.permission.CRYPT_KEEPER";
field public static final String DEVICE_POWER = "android.permission.DEVICE_POWER";
field public static final String DISABLE_SYSTEM_SOUND_EFFECTS = "android.permission.DISABLE_SYSTEM_SOUND_EFFECTS";
@@ -2333,6 +2334,17 @@ package android.companion {
}
package android.companion.virtual {
public final class VirtualDeviceManager {
}
public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable {
method public void close();
}
}
package android.content {
public class ApexEnvironment {

View File

@@ -54,6 +54,8 @@ import android.appwidget.AppWidgetManager;
import android.bluetooth.BluetoothManager;
import android.companion.CompanionDeviceManager;
import android.companion.ICompanionDeviceManager;
import android.companion.virtual.IVirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager;
import android.content.ClipboardManager;
import android.content.ContentCaptureOptions;
import android.content.Context;
@@ -875,6 +877,16 @@ public final class SystemServiceRegistry {
return new CompanionDeviceManager(service, ctx.getOuterContext());
}});
registerService(Context.VIRTUAL_DEVICE_SERVICE, VirtualDeviceManager.class,
new CachedServiceFetcher<VirtualDeviceManager>() {
@Override
public VirtualDeviceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IVirtualDeviceManager service = IVirtualDeviceManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.VIRTUAL_DEVICE_SERVICE));
return new VirtualDeviceManager(service, ctx.getOuterContext());
}});
registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
new CachedServiceFetcher<ConsumerIrManager>() {
@Override

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2021 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.companion.virtual;
/**
* Interface for a virtual device.
*
* @hide
*/
interface IVirtualDevice {
void close();
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2021 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.companion.virtual;
import android.companion.virtual.IVirtualDevice;
/**
* Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService.
*
* @hide
*/
interface IVirtualDeviceManager {
IVirtualDevice createVirtualDevice();
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2021 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.companion.virtual;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
/**
* System level service for managing virtual devices.
*
* @hide
*/
@SystemApi
@SystemService(Context.VIRTUAL_DEVICE_SERVICE)
public final class VirtualDeviceManager {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "VirtualDeviceManager";
private final IVirtualDeviceManager mService;
private final Context mContext;
/** @hide */
public VirtualDeviceManager(
@Nullable IVirtualDeviceManager service, @NonNull Context context) {
mService = service;
mContext = context;
}
/**
* Creates a virtual device.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Nullable
public VirtualDevice createVirtualDevice() {
// TODO(b/194949534): Add CDM association ID here and unhide this API
try {
IVirtualDevice virtualDevice = mService.createVirtualDevice();
return new VirtualDevice(mContext, virtualDevice);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* A virtual device has its own virtual display, audio output, microphone, and camera etc. The
* creator of a virtual device can take the output from the virtual display and stream it over
* to another device, and inject input events that are received from the remote device.
*/
public static class VirtualDevice implements AutoCloseable {
private final Context mContext;
private final IVirtualDevice mVirtualDevice;
private VirtualDevice(Context context, IVirtualDevice virtualDevice) {
mContext = context.getApplicationContext();
mVirtualDevice = virtualDevice;
}
/**
* Closes the virtual device, stopping and tearing down any virtual displays,
* audio policies, and event injection that's currently in progress.
*/
public void close() {
try {
mVirtualDevice.close();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}

View File

@@ -3799,6 +3799,7 @@ public abstract class Context {
//@hide: INCIDENT_COMPANION_SERVICE,
//@hide: STATS_COMPANION_SERVICE,
COMPANION_DEVICE_SERVICE,
//@hide: VIRTUAL_DEVICE_SERVICE,
CROSS_PROFILE_APPS_SERVICE,
//@hide: SYSTEM_UPDATE_SERVICE,
//@hide: TIME_DETECTOR_SERVICE,
@@ -5260,6 +5261,16 @@ public abstract class Context {
*/
public static final String COMPANION_DEVICE_SERVICE = "companiondevice";
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.companion.virtual.VirtualDeviceManager} for managing virtual devices.
*
* @see #getSystemService(String)
* @see android.companion.virtual.VirtualDeviceManager
* @hide
*/
public static final String VIRTUAL_DEVICE_SERVICE = "virtualdevice";
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.ConsumerIrManager} for transmitting infrared

View File

@@ -5911,6 +5911,11 @@
<permission android:name="android.permission.READ_GLOBAL_APP_SEARCH_DATA"
android:protectionLevel="internal|role" />
<!-- @SystemApi Allows an application to create virtual devices in VirtualDeviceManager.
@hide -->
<permission android:name="android.permission.CREATE_VIRTUAL_DEVICE"
android:protectionLevel="internal|role" />
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2021 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 com.android.server.companion.virtual;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceManager;
import android.content.Context;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.ExceptionUtils;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
/** @hide */
@SuppressLint("LongLogTag")
public class VirtualDeviceManagerService extends SystemService {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "VirtualDeviceManagerService";
private final VirtualDeviceManagerImpl mImpl;
@GuardedBy("mVirtualDevices")
private final ArrayList<VirtualDeviceImpl> mVirtualDevices = new ArrayList<>();
public VirtualDeviceManagerService(Context context) {
super(context);
mImpl = new VirtualDeviceManagerImpl();
}
@Override
public void onStart() {
publishBinderService(Context.VIRTUAL_DEVICE_SERVICE, mImpl);
}
private class VirtualDeviceImpl extends IVirtualDevice.Stub {
private VirtualDeviceImpl() {}
@Override
public void close() {
synchronized (mVirtualDevices) {
mVirtualDevices.remove(this);
}
}
}
class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub {
@Override
public IVirtualDevice createVirtualDevice() {
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"createVirtualDevice");
VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl();
synchronized (mVirtualDevices) {
mVirtualDevices.add(virtualDevice);
}
return virtualDevice;
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
try {
return super.onTransact(code, data, reply, flags);
} catch (Throwable e) {
Slog.e(LOG_TAG, "Error during IPC", e);
throw ExceptionUtils.propagate(e, RemoteException.class);
}
}
@Override
public void dump(@NonNull FileDescriptor fd,
@NonNull PrintWriter fout,
@Nullable String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), LOG_TAG, fout)) {
return;
}
fout.println("Created virtual devices: ");
synchronized (mVirtualDevices) {
for (VirtualDeviceImpl virtualDevice : mVirtualDevices) {
fout.println(virtualDevice.toString());
}
}
}
}
}

View File

@@ -251,6 +251,8 @@ public final class SystemServer implements Dumpable {
"com.android.server.print.PrintManagerService";
private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
"com.android.server.companion.CompanionDeviceManagerService";
private static final String VIRTUAL_DEVICE_MANAGER_SERVICE_CLASS =
"com.android.server.companion.virtual.VirtualDeviceManagerService";
private static final String STATS_COMPANION_APEX_PATH =
"/apex/com.android.os.statsd/javalib/service-statsd.jar";
private static final String SCHEDULING_APEX_PATH =
@@ -2322,6 +2324,11 @@ public final class SystemServer implements Dumpable {
t.traceBegin("StartCompanionDeviceManager");
mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
t.traceEnd();
// VirtualDeviceManager depends on CDM to control the associations.
t.traceBegin("StartVirtualDeviceManager");
mSystemServiceManager.startService(VIRTUAL_DEVICE_MANAGER_SERVICE_CLASS);
t.traceEnd();
}
t.traceBegin("StartRestrictionManager");