Loading core/api/system-current.txt +4 −6 Original line number Diff line number Diff line Loading @@ -2784,6 +2784,9 @@ package android.companion.virtual { public final class VirtualDeviceManager { method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.VirtualDeviceManager.VirtualDevice createVirtualDevice(int, @NonNull android.companion.virtual.VirtualDeviceParams); field public static final int LAUNCH_FAILURE_NO_ACTIVITY = 2; // 0x2 field public static final int LAUNCH_FAILURE_PENDING_INTENT_CANCELED = 1; // 0x1 field public static final int LAUNCH_SUCCESS = 0; // 0x0 } public static interface VirtualDeviceManager.ActivityListener { Loading @@ -2791,11 +2794,6 @@ package android.companion.virtual { method public void onTopActivityChanged(int, @NonNull android.content.ComponentName); } public static interface VirtualDeviceManager.LaunchCallback { method public void onLaunchFailed(); method public void onLaunchSuccess(); } public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable { method public void addActivityListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener); method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close(); Loading @@ -2804,7 +2802,7 @@ package android.companion.virtual { method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.LaunchCallback); method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer); method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean); } core/java/android/companion/virtual/VirtualDeviceManager.java +45 −28 Original line number Diff line number Diff line Loading @@ -17,13 +17,13 @@ package android.companion.virtual; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.Activity; import android.app.PendingIntent; import android.companion.AssociationInfo; import android.companion.virtual.audio.VirtualAudioDevice; Loading @@ -48,7 +48,12 @@ import android.os.ResultReceiver; import android.util.ArrayMap; import android.view.Surface; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.concurrent.Executor; import java.util.function.IntConsumer; /** * System level service for managing virtual devices. Loading @@ -70,6 +75,35 @@ public final class VirtualDeviceManager { | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( prefix = "LAUNCH_", value = { LAUNCH_SUCCESS, LAUNCH_FAILURE_PENDING_INTENT_CANCELED, LAUNCH_FAILURE_NO_ACTIVITY}) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface PendingIntentLaunchStatus {} /** * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch was * successful. */ public static final int LAUNCH_SUCCESS = 0; /** * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch failed * because the pending intent was canceled. */ public static final int LAUNCH_FAILURE_PENDING_INTENT_CANCELED = 1; /** * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch failed * because no activity starts were detected as a result of calling the pending intent. */ public static final int LAUNCH_FAILURE_NO_ACTIVITY = 2; private final IVirtualDeviceManager mService; private final Context mContext; Loading Loading @@ -173,16 +207,20 @@ public final class VirtualDeviceManager { * intent, the activity will be started on the virtual display using * {@link android.app.ActivityOptions#setLaunchDisplayId}. If the intent is a service or * broadcast intent, an attempt will be made to catch activities started as a result of * sending the pending intent and move them to the given display. * sending the pending intent and move them to the given display. When it completes, * {@code listener} will be called with the status of whether the launch attempt is * successful or not. * @param executor The executor to run {@code launchCallback} on. * @param launchCallback Callback that is called when the pending intent launching is * complete. * @param listener Listener that is called when the pending intent launching is complete. * The argument is {@link #LAUNCH_SUCCESS} if the launch successfully started an activity * on the virtual display, or one of the {@code LAUNCH_FAILED} status explaining why it * failed. */ public void launchPendingIntent( int displayId, @NonNull PendingIntent pendingIntent, @NonNull Executor executor, @NonNull LaunchCallback launchCallback) { @NonNull IntConsumer listener) { try { mVirtualDevice.launchPendingIntent( displayId, Loading @@ -191,13 +229,7 @@ public final class VirtualDeviceManager { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); executor.execute(() -> { if (resultCode == Activity.RESULT_OK) { launchCallback.onLaunchSuccess(); } else { launchCallback.onLaunchFailed(); } }); executor.execute(() -> listener.accept(resultCode)); } }); } catch (RemoteException e) { Loading Loading @@ -439,28 +471,13 @@ public final class VirtualDeviceManager { * {@link #addActivityListener}. * * @param listener The listener to remove. * @see #addActivityListener(ActivityListener, Executor) * @see #addActivityListener(Executor, ActivityListener) */ public void removeActivityListener(@NonNull ActivityListener listener) { mActivityListeners.remove(listener); } } /** * Callback for launching pending intents on the virtual device. */ public interface LaunchCallback { /** * Called when the pending intent launched successfully. */ void onLaunchSuccess(); /** * Called when the pending intent failed to launch. */ void onLaunchFailed(); } /** * Listener for activity changes in this virtual device. */ Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +17 −3 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.app.admin.DevicePolicyManager; import android.companion.AssociationInfo; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager.ActivityListener; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.audio.IAudioConfigChangedCallback; Loading Loading @@ -79,6 +80,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub implements IBinder.DeathRecipient { private static final String TAG = "VirtualDeviceImpl"; /** * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched. */ private static final long PENDING_TRAMPOLINE_TIMEOUT_MS = 5000; private final Object mVirtualDeviceLock = new Object(); private final Context mContext; Loading Loading @@ -195,20 +202,27 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub if (pendingIntent.isActivity()) { try { sendPendingIntent(displayId, pendingIntent); resultReceiver.send(Activity.RESULT_OK, null); resultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null); } catch (PendingIntent.CanceledException e) { Slog.w(TAG, "Pending intent canceled", e); resultReceiver.send(Activity.RESULT_CANCELED, null); resultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_PENDING_INTENT_CANCELED, null); } } else { PendingTrampoline pendingTrampoline = new PendingTrampoline(pendingIntent, resultReceiver, displayId); mPendingTrampolineCallback.startWaitingForPendingTrampoline(pendingTrampoline); mContext.getMainThreadHandler().postDelayed(() -> { pendingTrampoline.mResultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null); mPendingTrampolineCallback.stopWaitingForPendingTrampoline(pendingTrampoline); }, PENDING_TRAMPOLINE_TIMEOUT_MS); try { sendPendingIntent(displayId, pendingIntent); } catch (PendingIntent.CanceledException e) { Slog.w(TAG, "Pending intent canceled", e); resultReceiver.send(Activity.RESULT_CANCELED, null); resultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_PENDING_INTENT_CANCELED, null); mPendingTrampolineCallback.stopWaitingForPendingTrampoline(pendingTrampoline); } } Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +5 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static com.android.server.wm.ActivityInterceptorCallback.VIRTUAL_DEVICE_S import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityOptions; import android.companion.AssociationInfo; import android.companion.CompanionDeviceManager; Loading @@ -29,6 +28,7 @@ import android.companion.CompanionDeviceManager.OnAssociationsChangedListener; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.IVirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.content.Context; import android.os.Handler; Loading Loading @@ -64,7 +64,7 @@ public class VirtualDeviceManagerService extends SystemService { private final Object mVirtualDeviceManagerLock = new Object(); private final VirtualDeviceManagerImpl mImpl; private VirtualDeviceManagerInternal mLocalService; private final VirtualDeviceManagerInternal mLocalService; private final Handler mHandler = new Handler(Looper.getMainLooper()); private final PendingTrampolineMap mPendingTrampolines = new PendingTrampolineMap(mHandler); /** Loading Loading @@ -115,7 +115,7 @@ public class VirtualDeviceManagerService extends SystemService { if (pt == null) { return null; } pt.mResultReceiver.send(Activity.RESULT_OK, null); pt.mResultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null); ActivityOptions options = info.checkedOptions; if (options == null) { options = ActivityOptions.makeBasic(); Loading Loading @@ -314,7 +314,8 @@ public class VirtualDeviceManagerService extends SystemService { pendingTrampoline.mPendingIntent.getCreatorPackage(), pendingTrampoline); if (existing != null) { existing.mResultReceiver.send(Activity.RESULT_CANCELED, null); existing.mResultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null); } } Loading Loading
core/api/system-current.txt +4 −6 Original line number Diff line number Diff line Loading @@ -2784,6 +2784,9 @@ package android.companion.virtual { public final class VirtualDeviceManager { method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.VirtualDeviceManager.VirtualDevice createVirtualDevice(int, @NonNull android.companion.virtual.VirtualDeviceParams); field public static final int LAUNCH_FAILURE_NO_ACTIVITY = 2; // 0x2 field public static final int LAUNCH_FAILURE_PENDING_INTENT_CANCELED = 1; // 0x1 field public static final int LAUNCH_SUCCESS = 0; // 0x0 } public static interface VirtualDeviceManager.ActivityListener { Loading @@ -2791,11 +2794,6 @@ package android.companion.virtual { method public void onTopActivityChanged(int, @NonNull android.content.ComponentName); } public static interface VirtualDeviceManager.LaunchCallback { method public void onLaunchFailed(); method public void onLaunchSuccess(); } public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable { method public void addActivityListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener); method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close(); Loading @@ -2804,7 +2802,7 @@ package android.companion.virtual { method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.LaunchCallback); method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer); method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean); }
core/java/android/companion/virtual/VirtualDeviceManager.java +45 −28 Original line number Diff line number Diff line Loading @@ -17,13 +17,13 @@ package android.companion.virtual; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.Activity; import android.app.PendingIntent; import android.companion.AssociationInfo; import android.companion.virtual.audio.VirtualAudioDevice; Loading @@ -48,7 +48,12 @@ import android.os.ResultReceiver; import android.util.ArrayMap; import android.view.Surface; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.concurrent.Executor; import java.util.function.IntConsumer; /** * System level service for managing virtual devices. Loading @@ -70,6 +75,35 @@ public final class VirtualDeviceManager { | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( prefix = "LAUNCH_", value = { LAUNCH_SUCCESS, LAUNCH_FAILURE_PENDING_INTENT_CANCELED, LAUNCH_FAILURE_NO_ACTIVITY}) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface PendingIntentLaunchStatus {} /** * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch was * successful. */ public static final int LAUNCH_SUCCESS = 0; /** * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch failed * because the pending intent was canceled. */ public static final int LAUNCH_FAILURE_PENDING_INTENT_CANCELED = 1; /** * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch failed * because no activity starts were detected as a result of calling the pending intent. */ public static final int LAUNCH_FAILURE_NO_ACTIVITY = 2; private final IVirtualDeviceManager mService; private final Context mContext; Loading Loading @@ -173,16 +207,20 @@ public final class VirtualDeviceManager { * intent, the activity will be started on the virtual display using * {@link android.app.ActivityOptions#setLaunchDisplayId}. If the intent is a service or * broadcast intent, an attempt will be made to catch activities started as a result of * sending the pending intent and move them to the given display. * sending the pending intent and move them to the given display. When it completes, * {@code listener} will be called with the status of whether the launch attempt is * successful or not. * @param executor The executor to run {@code launchCallback} on. * @param launchCallback Callback that is called when the pending intent launching is * complete. * @param listener Listener that is called when the pending intent launching is complete. * The argument is {@link #LAUNCH_SUCCESS} if the launch successfully started an activity * on the virtual display, or one of the {@code LAUNCH_FAILED} status explaining why it * failed. */ public void launchPendingIntent( int displayId, @NonNull PendingIntent pendingIntent, @NonNull Executor executor, @NonNull LaunchCallback launchCallback) { @NonNull IntConsumer listener) { try { mVirtualDevice.launchPendingIntent( displayId, Loading @@ -191,13 +229,7 @@ public final class VirtualDeviceManager { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); executor.execute(() -> { if (resultCode == Activity.RESULT_OK) { launchCallback.onLaunchSuccess(); } else { launchCallback.onLaunchFailed(); } }); executor.execute(() -> listener.accept(resultCode)); } }); } catch (RemoteException e) { Loading Loading @@ -439,28 +471,13 @@ public final class VirtualDeviceManager { * {@link #addActivityListener}. * * @param listener The listener to remove. * @see #addActivityListener(ActivityListener, Executor) * @see #addActivityListener(Executor, ActivityListener) */ public void removeActivityListener(@NonNull ActivityListener listener) { mActivityListeners.remove(listener); } } /** * Callback for launching pending intents on the virtual device. */ public interface LaunchCallback { /** * Called when the pending intent launched successfully. */ void onLaunchSuccess(); /** * Called when the pending intent failed to launch. */ void onLaunchFailed(); } /** * Listener for activity changes in this virtual device. */ Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +17 −3 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.app.admin.DevicePolicyManager; import android.companion.AssociationInfo; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager.ActivityListener; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.audio.IAudioConfigChangedCallback; Loading Loading @@ -79,6 +80,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub implements IBinder.DeathRecipient { private static final String TAG = "VirtualDeviceImpl"; /** * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched. */ private static final long PENDING_TRAMPOLINE_TIMEOUT_MS = 5000; private final Object mVirtualDeviceLock = new Object(); private final Context mContext; Loading Loading @@ -195,20 +202,27 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub if (pendingIntent.isActivity()) { try { sendPendingIntent(displayId, pendingIntent); resultReceiver.send(Activity.RESULT_OK, null); resultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null); } catch (PendingIntent.CanceledException e) { Slog.w(TAG, "Pending intent canceled", e); resultReceiver.send(Activity.RESULT_CANCELED, null); resultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_PENDING_INTENT_CANCELED, null); } } else { PendingTrampoline pendingTrampoline = new PendingTrampoline(pendingIntent, resultReceiver, displayId); mPendingTrampolineCallback.startWaitingForPendingTrampoline(pendingTrampoline); mContext.getMainThreadHandler().postDelayed(() -> { pendingTrampoline.mResultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null); mPendingTrampolineCallback.stopWaitingForPendingTrampoline(pendingTrampoline); }, PENDING_TRAMPOLINE_TIMEOUT_MS); try { sendPendingIntent(displayId, pendingIntent); } catch (PendingIntent.CanceledException e) { Slog.w(TAG, "Pending intent canceled", e); resultReceiver.send(Activity.RESULT_CANCELED, null); resultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_PENDING_INTENT_CANCELED, null); mPendingTrampolineCallback.stopWaitingForPendingTrampoline(pendingTrampoline); } } Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +5 −4 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static com.android.server.wm.ActivityInterceptorCallback.VIRTUAL_DEVICE_S import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityOptions; import android.companion.AssociationInfo; import android.companion.CompanionDeviceManager; Loading @@ -29,6 +28,7 @@ import android.companion.CompanionDeviceManager.OnAssociationsChangedListener; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.IVirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.content.Context; import android.os.Handler; Loading Loading @@ -64,7 +64,7 @@ public class VirtualDeviceManagerService extends SystemService { private final Object mVirtualDeviceManagerLock = new Object(); private final VirtualDeviceManagerImpl mImpl; private VirtualDeviceManagerInternal mLocalService; private final VirtualDeviceManagerInternal mLocalService; private final Handler mHandler = new Handler(Looper.getMainLooper()); private final PendingTrampolineMap mPendingTrampolines = new PendingTrampolineMap(mHandler); /** Loading Loading @@ -115,7 +115,7 @@ public class VirtualDeviceManagerService extends SystemService { if (pt == null) { return null; } pt.mResultReceiver.send(Activity.RESULT_OK, null); pt.mResultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null); ActivityOptions options = info.checkedOptions; if (options == null) { options = ActivityOptions.makeBasic(); Loading Loading @@ -314,7 +314,8 @@ public class VirtualDeviceManagerService extends SystemService { pendingTrampoline.mPendingIntent.getCreatorPackage(), pendingTrampoline); if (existing != null) { existing.mResultReceiver.send(Activity.RESULT_CANCELED, null); existing.mResultReceiver.send( VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null); } } Loading