summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceInternal.java458
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceManager.java368
2 files changed, 502 insertions, 324 deletions
diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java
new file mode 100644
index 000000000000..045e4c6c77b1
--- /dev/null
+++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2023 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.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.PendingIntent;
+import android.companion.virtual.audio.VirtualAudioDevice;
+import android.companion.virtual.sensor.VirtualSensor;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
+import android.hardware.input.VirtualDpad;
+import android.hardware.input.VirtualDpadConfig;
+import android.hardware.input.VirtualKeyboard;
+import android.hardware.input.VirtualKeyboardConfig;
+import android.hardware.input.VirtualMouse;
+import android.hardware.input.VirtualMouseConfig;
+import android.hardware.input.VirtualNavigationTouchpad;
+import android.hardware.input.VirtualNavigationTouchpadConfig;
+import android.hardware.input.VirtualTouchscreen;
+import android.hardware.input.VirtualTouchscreenConfig;
+import android.media.AudioManager;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.util.ArrayMap;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.IntConsumer;
+
+/**
+ * An internal representation of a virtual device.
+ *
+ * @hide
+ */
+public class VirtualDeviceInternal {
+
+ private final Context mContext;
+ private final IVirtualDeviceManager mService;
+ private final IVirtualDevice mVirtualDevice;
+ private final Object mActivityListenersLock = new Object();
+ @GuardedBy("mActivityListenersLock")
+ private final ArrayMap<VirtualDeviceManager.ActivityListener, ActivityListenerDelegate>
+ mActivityListeners =
+ new ArrayMap<>();
+ private final Object mIntentInterceptorListenersLock = new Object();
+ @GuardedBy("mIntentInterceptorListenersLock")
+ private final ArrayMap<VirtualDeviceManager.IntentInterceptorCallback,
+ IntentInterceptorDelegate> mIntentInterceptorListeners =
+ new ArrayMap<>();
+ private final Object mSoundEffectListenersLock = new Object();
+ @GuardedBy("mSoundEffectListenersLock")
+ private final ArrayMap<VirtualDeviceManager.SoundEffectListener, SoundEffectListenerDelegate>
+ mSoundEffectListeners = new ArrayMap<>();
+ private final IVirtualDeviceActivityListener mActivityListenerBinder =
+ new IVirtualDeviceActivityListener.Stub() {
+
+ @Override
+ public void onTopActivityChanged(int displayId, ComponentName topActivity,
+ @UserIdInt int userId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mActivityListenersLock) {
+ for (int i = 0; i < mActivityListeners.size(); i++) {
+ mActivityListeners.valueAt(i)
+ .onTopActivityChanged(displayId, topActivity);
+ mActivityListeners.valueAt(i)
+ .onTopActivityChanged(displayId, topActivity, userId);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void onDisplayEmpty(int displayId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mActivityListenersLock) {
+ for (int i = 0; i < mActivityListeners.size(); i++) {
+ mActivityListeners.valueAt(i).onDisplayEmpty(displayId);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+ private final IVirtualDeviceSoundEffectListener mSoundEffectListener =
+ new IVirtualDeviceSoundEffectListener.Stub() {
+ @Override
+ public void onPlaySoundEffect(int soundEffect) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSoundEffectListenersLock) {
+ for (int i = 0; i < mSoundEffectListeners.size(); i++) {
+ mSoundEffectListeners.valueAt(i).onPlaySoundEffect(soundEffect);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+ @Nullable
+ private VirtualAudioDevice mVirtualAudioDevice;
+
+ VirtualDeviceInternal(
+ IVirtualDeviceManager service,
+ Context context,
+ int associationId,
+ VirtualDeviceParams params) throws RemoteException {
+ mService = service;
+ mContext = context.getApplicationContext();
+ mVirtualDevice = service.createVirtualDevice(
+ new Binder(),
+ mContext.getPackageName(),
+ associationId,
+ params,
+ mActivityListenerBinder,
+ mSoundEffectListener);
+ }
+
+ int getDeviceId() {
+ try {
+ return mVirtualDevice.getDeviceId();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull Context createContext() {
+ try {
+ return mContext.createDeviceContext(mVirtualDevice.getDeviceId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull
+ List<VirtualSensor> getVirtualSensorList() {
+ try {
+ return mVirtualDevice.getVirtualSensorList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void launchPendingIntent(
+ int displayId,
+ @NonNull PendingIntent pendingIntent,
+ @NonNull Executor executor,
+ @NonNull IntConsumer listener) {
+ try {
+ mVirtualDevice.launchPendingIntent(
+ displayId,
+ pendingIntent,
+ new ResultReceiver(new Handler(Looper.getMainLooper())) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ super.onReceiveResult(resultCode, resultData);
+ executor.execute(() -> listener.accept(resultCode));
+ }
+ });
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ @Nullable
+ VirtualDisplay createVirtualDisplay(
+ @NonNull VirtualDisplayConfig config,
+ @Nullable @CallbackExecutor Executor executor,
+ @Nullable VirtualDisplay.Callback callback) {
+ IVirtualDisplayCallback callbackWrapper =
+ new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor);
+ final int displayId;
+ try {
+ displayId = mService.createVirtualDisplay(config, callbackWrapper, mVirtualDevice,
+ mContext.getPackageName());
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
+ return displayManager.createVirtualDisplayWrapper(config, callbackWrapper,
+ displayId);
+ }
+
+ void close() {
+ try {
+ // This also takes care of unregistering all virtual sensors.
+ mVirtualDevice.close();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ if (mVirtualAudioDevice != null) {
+ mVirtualAudioDevice.close();
+ mVirtualAudioDevice = null;
+ }
+ }
+
+ @NonNull
+ VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) {
+ try {
+ final IBinder token = new Binder(
+ "android.hardware.input.VirtualDpad:" + config.getInputDeviceName());
+ mVirtualDevice.createVirtualDpad(config, token);
+ return new VirtualDpad(mVirtualDevice, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull
+ VirtualKeyboard createVirtualKeyboard(@NonNull VirtualKeyboardConfig config) {
+ try {
+ final IBinder token = new Binder(
+ "android.hardware.input.VirtualKeyboard:" + config.getInputDeviceName());
+ mVirtualDevice.createVirtualKeyboard(config, token);
+ return new VirtualKeyboard(mVirtualDevice, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull
+ VirtualMouse createVirtualMouse(@NonNull VirtualMouseConfig config) {
+ try {
+ final IBinder token = new Binder(
+ "android.hardware.input.VirtualMouse:" + config.getInputDeviceName());
+ mVirtualDevice.createVirtualMouse(config, token);
+ return new VirtualMouse(mVirtualDevice, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull
+ VirtualTouchscreen createVirtualTouchscreen(
+ @NonNull VirtualTouchscreenConfig config) {
+ try {
+ final IBinder token = new Binder(
+ "android.hardware.input.VirtualTouchscreen:" + config.getInputDeviceName());
+ mVirtualDevice.createVirtualTouchscreen(config, token);
+ return new VirtualTouchscreen(mVirtualDevice, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull
+ VirtualNavigationTouchpad createVirtualNavigationTouchpad(
+ @NonNull VirtualNavigationTouchpadConfig config) {
+ try {
+ final IBinder token = new Binder(
+ "android.hardware.input.VirtualNavigationTouchpad:"
+ + config.getInputDeviceName());
+ mVirtualDevice.createVirtualNavigationTouchpad(config, token);
+ return new VirtualNavigationTouchpad(mVirtualDevice, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @NonNull
+ VirtualAudioDevice createVirtualAudioDevice(
+ @NonNull VirtualDisplay display,
+ @Nullable Executor executor,
+ @Nullable VirtualAudioDevice.AudioConfigurationChangeCallback callback) {
+ if (mVirtualAudioDevice == null) {
+ mVirtualAudioDevice = new VirtualAudioDevice(mContext, mVirtualDevice, display,
+ executor, callback, () -> mVirtualAudioDevice = null);
+ }
+ return mVirtualAudioDevice;
+ }
+
+ @NonNull
+ void setShowPointerIcon(boolean showPointerIcon) {
+ try {
+ mVirtualDevice.setShowPointerIcon(showPointerIcon);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void addActivityListener(
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull VirtualDeviceManager.ActivityListener listener) {
+ final ActivityListenerDelegate delegate = new ActivityListenerDelegate(
+ Objects.requireNonNull(listener), Objects.requireNonNull(executor));
+ synchronized (mActivityListenersLock) {
+ mActivityListeners.put(listener, delegate);
+ }
+ }
+
+ void removeActivityListener(@NonNull VirtualDeviceManager.ActivityListener listener) {
+ synchronized (mActivityListenersLock) {
+ mActivityListeners.remove(Objects.requireNonNull(listener));
+ }
+ }
+
+ void addSoundEffectListener(@CallbackExecutor @NonNull Executor executor,
+ @NonNull VirtualDeviceManager.SoundEffectListener soundEffectListener) {
+ final SoundEffectListenerDelegate delegate =
+ new SoundEffectListenerDelegate(Objects.requireNonNull(executor),
+ Objects.requireNonNull(soundEffectListener));
+ synchronized (mSoundEffectListenersLock) {
+ mSoundEffectListeners.put(soundEffectListener, delegate);
+ }
+ }
+
+ void removeSoundEffectListener(
+ @NonNull VirtualDeviceManager.SoundEffectListener soundEffectListener) {
+ synchronized (mSoundEffectListenersLock) {
+ mSoundEffectListeners.remove(Objects.requireNonNull(soundEffectListener));
+ }
+ }
+
+ void registerIntentInterceptor(
+ @NonNull IntentFilter interceptorFilter,
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull VirtualDeviceManager.IntentInterceptorCallback interceptorCallback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(interceptorFilter);
+ Objects.requireNonNull(interceptorCallback);
+ final IntentInterceptorDelegate delegate =
+ new IntentInterceptorDelegate(executor, interceptorCallback);
+ try {
+ mVirtualDevice.registerIntentInterceptor(delegate, interceptorFilter);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ synchronized (mIntentInterceptorListenersLock) {
+ mIntentInterceptorListeners.put(interceptorCallback, delegate);
+ }
+ }
+
+ void unregisterIntentInterceptor(
+ @NonNull VirtualDeviceManager.IntentInterceptorCallback interceptorCallback) {
+ Objects.requireNonNull(interceptorCallback);
+ final IntentInterceptorDelegate delegate;
+ synchronized (mIntentInterceptorListenersLock) {
+ delegate = mIntentInterceptorListeners.remove(interceptorCallback);
+ }
+ if (delegate != null) {
+ try {
+ mVirtualDevice.unregisterIntentInterceptor(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * A wrapper for {@link VirtualDeviceManager.ActivityListener} that executes callbacks on the
+ * given executor.
+ */
+ private static class ActivityListenerDelegate {
+ @NonNull private final VirtualDeviceManager.ActivityListener mActivityListener;
+ @NonNull private final Executor mExecutor;
+
+ ActivityListenerDelegate(@NonNull VirtualDeviceManager.ActivityListener listener,
+ @NonNull Executor executor) {
+ mActivityListener = listener;
+ mExecutor = executor;
+ }
+
+ public void onTopActivityChanged(int displayId, ComponentName topActivity) {
+ mExecutor.execute(() -> mActivityListener.onTopActivityChanged(displayId, topActivity));
+ }
+
+ public void onTopActivityChanged(int displayId, ComponentName topActivity,
+ @UserIdInt int userId) {
+ mExecutor.execute(() ->
+ mActivityListener.onTopActivityChanged(displayId, topActivity, userId));
+ }
+
+ public void onDisplayEmpty(int displayId) {
+ mExecutor.execute(() -> mActivityListener.onDisplayEmpty(displayId));
+ }
+ }
+
+ /**
+ * A wrapper for {@link VirtualDeviceManager.IntentInterceptorCallback} that executes callbacks
+ * on the given executor.
+ */
+ private static class IntentInterceptorDelegate extends IVirtualDeviceIntentInterceptor.Stub {
+ @NonNull private final VirtualDeviceManager.IntentInterceptorCallback
+ mIntentInterceptorCallback;
+ @NonNull private final Executor mExecutor;
+
+ private IntentInterceptorDelegate(Executor executor,
+ VirtualDeviceManager.IntentInterceptorCallback interceptorCallback) {
+ mExecutor = executor;
+ mIntentInterceptorCallback = interceptorCallback;
+ }
+
+ @Override
+ public void onIntentIntercepted(Intent intent) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mIntentInterceptorCallback.onIntentIntercepted(intent));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ /**
+ * A wrapper for {@link VirtualDeviceManager.SoundEffectListener} that executes callbacks on the
+ * given executor.
+ */
+ private static class SoundEffectListenerDelegate {
+ @NonNull private final VirtualDeviceManager.SoundEffectListener mSoundEffectListener;
+ @NonNull private final Executor mExecutor;
+
+ private SoundEffectListenerDelegate(Executor executor,
+ VirtualDeviceManager.SoundEffectListener soundEffectCallback) {
+ mSoundEffectListener = soundEffectCallback;
+ mExecutor = executor;
+ }
+
+ public void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType) {
+ mExecutor.execute(() -> mSoundEffectListener.onPlaySoundEffect(effectType));
+ }
+ }
+}
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index cb9f06c39393..d3d635e19f2e 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -40,8 +40,6 @@ import android.content.IntentFilter;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.VirtualDisplayFlag;
-import android.hardware.display.DisplayManagerGlobal;
-import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplay;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.VirtualDpad;
@@ -55,26 +53,17 @@ import android.hardware.input.VirtualNavigationTouchpadConfig;
import android.hardware.input.VirtualTouchscreen;
import android.hardware.input.VirtualTouchscreenConfig;
import android.media.AudioManager;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.ArrayMap;
import android.util.Log;
import android.view.Surface;
-import com.android.internal.annotations.GuardedBy;
-
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.IntConsumer;
@@ -337,75 +326,7 @@ public final class VirtualDeviceManager {
@SystemApi
public static class VirtualDevice implements AutoCloseable {
- private final Context mContext;
- private final IVirtualDeviceManager mService;
- private final IVirtualDevice mVirtualDevice;
- private final Object mActivityListenersLock = new Object();
- @GuardedBy("mActivityListenersLock")
- private final ArrayMap<ActivityListener, ActivityListenerDelegate> mActivityListeners =
- new ArrayMap<>();
- private final Object mIntentInterceptorListenersLock = new Object();
- @GuardedBy("mIntentInterceptorListenersLock")
- private final ArrayMap<IntentInterceptorCallback,
- VirtualIntentInterceptorDelegate> mIntentInterceptorListeners =
- new ArrayMap<>();
- private final Object mSoundEffectListenersLock = new Object();
- @GuardedBy("mSoundEffectListenersLock")
- private final ArrayMap<SoundEffectListener, SoundEffectListenerDelegate>
- mSoundEffectListeners = new ArrayMap<>();
- private final IVirtualDeviceActivityListener mActivityListenerBinder =
- new IVirtualDeviceActivityListener.Stub() {
-
- @Override
- public void onTopActivityChanged(int displayId, ComponentName topActivity,
- @UserIdInt int userId) {
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mActivityListenersLock) {
- for (int i = 0; i < mActivityListeners.size(); i++) {
- mActivityListeners.valueAt(i)
- .onTopActivityChanged(displayId, topActivity);
- mActivityListeners.valueAt(i)
- .onTopActivityChanged(displayId, topActivity, userId);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onDisplayEmpty(int displayId) {
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mActivityListenersLock) {
- for (int i = 0; i < mActivityListeners.size(); i++) {
- mActivityListeners.valueAt(i).onDisplayEmpty(displayId);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- };
- private final IVirtualDeviceSoundEffectListener mSoundEffectListener =
- new IVirtualDeviceSoundEffectListener.Stub() {
- @Override
- public void onPlaySoundEffect(int soundEffect) {
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSoundEffectListenersLock) {
- for (int i = 0; i < mSoundEffectListeners.size(); i++) {
- mSoundEffectListeners.valueAt(i).onPlaySoundEffect(soundEffect);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- };
- @Nullable
- private VirtualAudioDevice mVirtualAudioDevice;
+ private final VirtualDeviceInternal mVirtualDeviceInternal;
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
private VirtualDevice(
@@ -413,26 +334,15 @@ public final class VirtualDeviceManager {
Context context,
int associationId,
VirtualDeviceParams params) throws RemoteException {
- mService = service;
- mContext = context.getApplicationContext();
- mVirtualDevice = service.createVirtualDevice(
- new Binder(),
- mContext.getPackageName(),
- associationId,
- params,
- mActivityListenerBinder,
- mSoundEffectListener);
+ mVirtualDeviceInternal =
+ new VirtualDeviceInternal(service, context, associationId, params);
}
/**
* Returns the unique ID of this virtual device.
*/
public int getDeviceId() {
- try {
- return mVirtualDevice.getDeviceId();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.getDeviceId();
}
/**
@@ -440,11 +350,7 @@ public final class VirtualDeviceManager {
* calling {@link Context#createDeviceContext(int)} with the device id of this device.
*/
public @NonNull Context createContext() {
- try {
- return mContext.createDeviceContext(mVirtualDevice.getDeviceId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.createContext();
}
/**
@@ -456,11 +362,7 @@ public final class VirtualDeviceManager {
*/
@NonNull
public List<VirtualSensor> getVirtualSensorList() {
- try {
- return mVirtualDevice.getVirtualSensorList();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.getVirtualSensorList();
}
/**
@@ -486,20 +388,8 @@ public final class VirtualDeviceManager {
@NonNull PendingIntent pendingIntent,
@NonNull Executor executor,
@NonNull IntConsumer listener) {
- try {
- mVirtualDevice.launchPendingIntent(
- displayId,
- pendingIntent,
- new ResultReceiver(new Handler(Looper.getMainLooper())) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- super.onReceiveResult(resultCode, resultData);
- executor.execute(() -> listener.accept(resultCode));
- }
- });
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ mVirtualDeviceInternal.launchPendingIntent(
+ displayId, pendingIntent, executor, listener);
}
/**
@@ -540,7 +430,7 @@ public final class VirtualDeviceManager {
@VirtualDisplayFlag int flags,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
- // Currently this just use the device ID, which means all of the virtual displays
+ // Currently this just uses the device ID, which means all of the virtual displays
// created using the same virtual device will have the same name if they use this
// deprecated API. The name should only be used for informational purposes, and not for
// identifying the display in code.
@@ -551,7 +441,7 @@ public final class VirtualDeviceManager {
if (surface != null) {
builder.setSurface(surface);
}
- return createVirtualDisplay(builder.build(), executor, callback);
+ return mVirtualDeviceInternal.createVirtualDisplay(builder.build(), executor, callback);
}
/**
@@ -573,18 +463,7 @@ public final class VirtualDeviceManager {
@NonNull VirtualDisplayConfig config,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
- IVirtualDisplayCallback callbackWrapper =
- new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor);
- final int displayId;
- try {
- displayId = mService.createVirtualDisplay(config, callbackWrapper, mVirtualDevice,
- mContext.getPackageName());
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
- return displayManager.createVirtualDisplayWrapper(config, callbackWrapper,
- displayId);
+ return mVirtualDeviceInternal.createVirtualDisplay(config, executor, callback);
}
/**
@@ -593,16 +472,7 @@ public final class VirtualDeviceManager {
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void close() {
- try {
- // This also takes care of unregistering all virtual sensors.
- mVirtualDevice.close();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- if (mVirtualAudioDevice != null) {
- mVirtualAudioDevice.close();
- mVirtualAudioDevice = null;
- }
+ mVirtualDeviceInternal.close();
}
/**
@@ -613,14 +483,7 @@ public final class VirtualDeviceManager {
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) {
- try {
- final IBinder token = new Binder(
- "android.hardware.input.VirtualDpad:" + config.getInputDeviceName());
- mVirtualDevice.createVirtualDpad(config, token);
- return new VirtualDpad(mVirtualDevice, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.createVirtualDpad(config);
}
/**
@@ -631,14 +494,7 @@ public final class VirtualDeviceManager {
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualKeyboard createVirtualKeyboard(@NonNull VirtualKeyboardConfig config) {
- try {
- final IBinder token = new Binder(
- "android.hardware.input.VirtualKeyboard:" + config.getInputDeviceName());
- mVirtualDevice.createVirtualKeyboard(config, token);
- return new VirtualKeyboard(mVirtualDevice, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.createVirtualKeyboard(config);
}
/**
@@ -664,7 +520,7 @@ public final class VirtualDeviceManager {
.setInputDeviceName(inputDeviceName)
.setAssociatedDisplayId(display.getDisplay().getDisplayId())
.build();
- return createVirtualKeyboard(keyboardConfig);
+ return mVirtualDeviceInternal.createVirtualKeyboard(keyboardConfig);
}
/**
@@ -675,14 +531,7 @@ public final class VirtualDeviceManager {
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualMouse createVirtualMouse(@NonNull VirtualMouseConfig config) {
- try {
- final IBinder token = new Binder(
- "android.hardware.input.VirtualMouse:" + config.getInputDeviceName());
- mVirtualDevice.createVirtualMouse(config, token);
- return new VirtualMouse(mVirtualDevice, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.createVirtualMouse(config);
}
/**
@@ -709,7 +558,7 @@ public final class VirtualDeviceManager {
.setInputDeviceName(inputDeviceName)
.setAssociatedDisplayId(display.getDisplay().getDisplayId())
.build();
- return createVirtualMouse(mouseConfig);
+ return mVirtualDeviceInternal.createVirtualMouse(mouseConfig);
}
/**
@@ -721,38 +570,7 @@ public final class VirtualDeviceManager {
@NonNull
public VirtualTouchscreen createVirtualTouchscreen(
@NonNull VirtualTouchscreenConfig config) {
- try {
- final IBinder token = new Binder(
- "android.hardware.input.VirtualTouchscreen:" + config.getInputDeviceName());
- mVirtualDevice.createVirtualTouchscreen(config, token);
- return new VirtualTouchscreen(mVirtualDevice, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Creates a virtual touchpad in navigation mode.
- *
- * A touchpad in navigation mode means that its events are interpreted as navigation events
- * (up, down, etc) instead of using them to update a cursor's absolute position. If the
- * events are not consumed they are converted to DPAD events.
- *
- * @param config the configurations of the virtual navigation touchpad.
- */
- @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
- @NonNull
- public VirtualNavigationTouchpad createVirtualNavigationTouchpad(
- @NonNull VirtualNavigationTouchpadConfig config) {
- try {
- final IBinder token = new Binder(
- "android.hardware.input.VirtualNavigationTouchpad:"
- + config.getInputDeviceName());
- mVirtualDevice.createVirtualNavigationTouchpad(config, token);
- return new VirtualNavigationTouchpad(mVirtualDevice, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mVirtualDeviceInternal.createVirtualTouchscreen(config);
}
/**
@@ -781,7 +599,23 @@ public final class VirtualDeviceManager {
.setInputDeviceName(inputDeviceName)
.setAssociatedDisplayId(display.getDisplay().getDisplayId())
.build();
- return createVirtualTouchscreen(touchscreenConfig);
+ return mVirtualDeviceInternal.createVirtualTouchscreen(touchscreenConfig);
+ }
+
+ /**
+ * Creates a virtual touchpad in navigation mode.
+ *
+ * A touchpad in navigation mode means that its events are interpreted as navigation events
+ * (up, down, etc) instead of using them to update a cursor's absolute position. If the
+ * events are not consumed they are converted to DPAD events.
+ *
+ * @param config the configurations of the virtual navigation touchpad.
+ */
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ @NonNull
+ public VirtualNavigationTouchpad createVirtualNavigationTouchpad(
+ @NonNull VirtualNavigationTouchpadConfig config) {
+ return mVirtualDeviceInternal.createVirtualNavigationTouchpad(config);
}
/**
@@ -807,11 +641,7 @@ public final class VirtualDeviceManager {
@NonNull VirtualDisplay display,
@Nullable Executor executor,
@Nullable AudioConfigurationChangeCallback callback) {
- if (mVirtualAudioDevice == null) {
- mVirtualAudioDevice = new VirtualAudioDevice(mContext, mVirtualDevice, display,
- executor, callback, () -> mVirtualAudioDevice = null);
- }
- return mVirtualAudioDevice;
+ return mVirtualDeviceInternal.createVirtualAudioDevice(display, executor, callback);
}
/**
@@ -823,11 +653,7 @@ public final class VirtualDeviceManager {
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public void setShowPointerIcon(boolean showPointerIcon) {
- try {
- mVirtualDevice.setShowPointerIcon(showPointerIcon);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mVirtualDeviceInternal.setShowPointerIcon(showPointerIcon);
}
/**
@@ -840,11 +666,7 @@ public final class VirtualDeviceManager {
*/
public void addActivityListener(
@CallbackExecutor @NonNull Executor executor, @NonNull ActivityListener listener) {
- final ActivityListenerDelegate delegate = new ActivityListenerDelegate(
- Objects.requireNonNull(listener), Objects.requireNonNull(executor));
- synchronized (mActivityListenersLock) {
- mActivityListeners.put(listener, delegate);
- }
+ mVirtualDeviceInternal.addActivityListener(executor, listener);
}
/**
@@ -855,9 +677,7 @@ public final class VirtualDeviceManager {
* @see #addActivityListener(Executor, ActivityListener)
*/
public void removeActivityListener(@NonNull ActivityListener listener) {
- synchronized (mActivityListenersLock) {
- mActivityListeners.remove(Objects.requireNonNull(listener));
- }
+ mVirtualDeviceInternal.removeActivityListener(listener);
}
/**
@@ -869,12 +689,7 @@ public final class VirtualDeviceManager {
*/
public void addSoundEffectListener(@CallbackExecutor @NonNull Executor executor,
@NonNull SoundEffectListener soundEffectListener) {
- final SoundEffectListenerDelegate delegate =
- new SoundEffectListenerDelegate(Objects.requireNonNull(executor),
- Objects.requireNonNull(soundEffectListener));
- synchronized (mSoundEffectListenersLock) {
- mSoundEffectListeners.put(soundEffectListener, delegate);
- }
+ mVirtualDeviceInternal.addSoundEffectListener(executor, soundEffectListener);
}
/**
@@ -884,9 +699,7 @@ public final class VirtualDeviceManager {
* @see #addActivityListener(Executor, ActivityListener)
*/
public void removeSoundEffectListener(@NonNull SoundEffectListener soundEffectListener) {
- synchronized (mSoundEffectListenersLock) {
- mSoundEffectListeners.remove(Objects.requireNonNull(soundEffectListener));
- }
+ mVirtualDeviceInternal.removeSoundEffectListener(soundEffectListener);
}
/**
@@ -905,19 +718,8 @@ public final class VirtualDeviceManager {
@NonNull IntentFilter interceptorFilter,
@CallbackExecutor @NonNull Executor executor,
@NonNull IntentInterceptorCallback interceptorCallback) {
- Objects.requireNonNull(executor);
- Objects.requireNonNull(interceptorFilter);
- Objects.requireNonNull(interceptorCallback);
- final VirtualIntentInterceptorDelegate delegate =
- new VirtualIntentInterceptorDelegate(executor, interceptorCallback);
- try {
- mVirtualDevice.registerIntentInterceptor(delegate, interceptorFilter);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- synchronized (mIntentInterceptorListenersLock) {
- mIntentInterceptorListeners.put(interceptorCallback, delegate);
- }
+ mVirtualDeviceInternal.registerIntentInterceptor(
+ interceptorFilter, executor, interceptorCallback);
}
/**
@@ -927,18 +729,7 @@ public final class VirtualDeviceManager {
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void unregisterIntentInterceptor(
@NonNull IntentInterceptorCallback interceptorCallback) {
- Objects.requireNonNull(interceptorCallback);
- final VirtualIntentInterceptorDelegate delegate;
- synchronized (mIntentInterceptorListenersLock) {
- delegate = mIntentInterceptorListeners.remove(interceptorCallback);
- }
- if (delegate != null) {
- try {
- mVirtualDevice.unregisterIntentInterceptor(delegate);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
+ mVirtualDeviceInternal.unregisterIntentInterceptor(interceptorCallback);
}
}
@@ -987,33 +778,6 @@ public final class VirtualDeviceManager {
}
/**
- * A wrapper for {@link ActivityListener} that executes callbacks on the given executor.
- */
- private static class ActivityListenerDelegate {
- @NonNull private final ActivityListener mActivityListener;
- @NonNull private final Executor mExecutor;
-
- ActivityListenerDelegate(@NonNull ActivityListener listener, @NonNull Executor executor) {
- mActivityListener = listener;
- mExecutor = executor;
- }
-
- public void onTopActivityChanged(int displayId, ComponentName topActivity) {
- mExecutor.execute(() -> mActivityListener.onTopActivityChanged(displayId, topActivity));
- }
-
- public void onTopActivityChanged(int displayId, ComponentName topActivity,
- @UserIdInt int userId) {
- mExecutor.execute(() ->
- mActivityListener.onTopActivityChanged(displayId, topActivity, userId));
- }
-
- public void onDisplayEmpty(int displayId) {
- mExecutor.execute(() -> mActivityListener.onDisplayEmpty(displayId));
- }
- }
-
- /**
* Interceptor interface to be called when an intent matches the IntentFilter passed into {@link
* VirtualDevice#registerIntentInterceptor}. When the interceptor is called after matching the
* IntentFilter, the intended activity launch will be aborted and alternatively replaced by
@@ -1035,32 +799,6 @@ public final class VirtualDeviceManager {
}
/**
- * A wrapper for {@link IntentInterceptorCallback} that executes callbacks on the
- * the given executor.
- */
- private static class VirtualIntentInterceptorDelegate
- extends IVirtualDeviceIntentInterceptor.Stub {
- @NonNull private final IntentInterceptorCallback mIntentInterceptorCallback;
- @NonNull private final Executor mExecutor;
-
- private VirtualIntentInterceptorDelegate(Executor executor,
- IntentInterceptorCallback interceptorCallback) {
- mExecutor = executor;
- mIntentInterceptorCallback = interceptorCallback;
- }
-
- @Override
- public void onIntentIntercepted(Intent intent) {
- final long token = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mIntentInterceptorCallback.onIntentIntercepted(intent));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
- /**
* Listener for system sound effect playback on virtual device.
* @hide
*/
@@ -1075,22 +813,4 @@ public final class VirtualDeviceManager {
*/
void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType);
}
-
- /**
- * A wrapper for {@link SoundEffectListener} that executes callbacks on the given executor.
- */
- private static class SoundEffectListenerDelegate {
- @NonNull private final SoundEffectListener mSoundEffectListener;
- @NonNull private final Executor mExecutor;
-
- private SoundEffectListenerDelegate(Executor executor,
- SoundEffectListener soundEffectCallback) {
- mSoundEffectListener = soundEffectCallback;
- mExecutor = executor;
- }
-
- public void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType) {
- mExecutor.execute(() -> mSoundEffectListener.onPlaySoundEffect(effectType));
- }
- }
}