Loading services/companion/java/com/android/server/companion/virtual/computercontrol/ComputerControlSessionImpl.java +18 −5 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub private final IBinder mAppToken; private final ComputerControlSessionParams mParams; private final String mOwnerPackageName; private final OnClosedListener mOnClosedListener; private final IVirtualDevice mVirtualDevice; private final int mVirtualDisplayId; Loading @@ -120,6 +121,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub OnClosedListener onClosedListener, Injector injector) { mAppToken = appToken; mParams = params; mOwnerPackageName = attributionSource.getPackageName(); mOnClosedListener = onClosedListener; mInjector = injector; Loading Loading @@ -184,7 +186,10 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub mVirtualDevice.setDisplayImePolicy( mVirtualDisplayId, WindowManager.DISPLAY_IME_POLICY_HIDE); final String dpadName = mParams.getName() + "-dpad"; final String inputDeviceNamePrefix = attributionSource.getPackageName() + ":" + mParams.getName(); final String dpadName = inputDeviceNamePrefix + "-dpad"; final VirtualDpadConfig virtualDpadConfig = new VirtualDpadConfig.Builder() .setAssociatedDisplayId(mVirtualDisplayId) Loading @@ -193,7 +198,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub mVirtualDpad = mVirtualDevice.createVirtualDpad( virtualDpadConfig, new Binder(dpadName)); final String keyboardName = mParams.getName() + "-keyboard"; final String keyboardName = inputDeviceNamePrefix + "-keyboard"; final VirtualKeyboardConfig virtualKeyboardConfig = new VirtualKeyboardConfig.Builder() .setAssociatedDisplayId(mVirtualDisplayId) Loading @@ -202,7 +207,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub mVirtualKeyboard = mVirtualDevice.createVirtualKeyboard( virtualKeyboardConfig, new Binder(keyboardName)); final String touchscreenName = mParams.getName() + "-touchscreen"; final String touchscreenName = inputDeviceNamePrefix + "-touchscreen"; final VirtualTouchscreenConfig virtualTouchscreenConfig = new VirtualTouchscreenConfig.Builder(mDisplayWidth, mDisplayHeight) .setAssociatedDisplayId(mVirtualDisplayId) Loading Loading @@ -252,6 +257,14 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub return mVirtualDisplayToken; } String getName() { return mParams.getName(); } String getOwnerPackageName() { return mOwnerPackageName; } public void launchApplication(@NonNull String packageName) { if (!mParams.getTargetPackageNames().contains(Objects.requireNonNull(packageName))) { throw new IllegalArgumentException( Loading Loading @@ -360,7 +373,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub public void close() throws RemoteException { mVirtualDevice.close(); mAppToken.unlinkToDeath(this, 0); mOnClosedListener.onClosed(asBinder()); mOnClosedListener.onClosed(this); } @Override Loading Loading @@ -458,7 +471,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub /** Interface for listening for closing of sessions. */ interface OnClosedListener { void onClosed(IBinder token); void onClosed(ComputerControlSessionImpl session); } @VisibleForTesting Loading services/companion/java/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessor.java +20 −6 Original line number Diff line number Diff line Loading @@ -54,6 +54,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.ServiceThread; import java.util.Objects; /** * Handles creation and lifecycle of {@link ComputerControlSession}s. * Loading @@ -76,7 +78,7 @@ public class ComputerControlSessionProcessor { private final PendingIntentFactory mPendingIntentFactory; /** The binders of all currently active sessions. */ private final ArraySet<IBinder> mSessions = new ArraySet<>(); private final ArraySet<ComputerControlSessionImpl> mSessions = new ArraySet<>(); private final Object mHandlerThreadLock = new Object(); @GuardedBy("mHandlerThreadLock") Loading Loading @@ -111,7 +113,7 @@ public class ComputerControlSessionProcessor { @NonNull AttributionSource attributionSource, @NonNull ComputerControlSessionParams params, @NonNull IComputerControlSessionCallback callback) { validateParams(params); validateParams(attributionSource, params); startHandlerThreadIfNeeded(); final boolean canCreateWithoutConsent; Loading Loading @@ -150,7 +152,19 @@ public class ComputerControlSessionProcessor { } } private void validateParams(ComputerControlSessionParams params) { private void validateParams(AttributionSource attributionSource, ComputerControlSessionParams params) { synchronized (mSessions) { for (int i = 0; i < mSessions.size(); i++) { ComputerControlSessionImpl session = mSessions.valueAt(i); if (Objects.equals(attributionSource.getPackageName(), session.getOwnerPackageName()) && Objects.equals(params.getName(), session.getName())) { throw new IllegalArgumentException("Session name must be unique"); } } } if (!Flags.computerControlActivityPolicyStrict()) { return; } Loading Loading @@ -207,7 +221,7 @@ public class ComputerControlSessionProcessor { callback.asBinder(), params, attributionSource, mVirtualDeviceFactory, new OnSessionClosedListener(params.getName(), callback), new ComputerControlSessionImpl.Injector(mContext)); mSessions.add(session.asBinder()); mSessions.add(session); } // If the client provided a surface, disable the screenshot API. Loading Loading @@ -321,9 +335,9 @@ public class ComputerControlSessionProcessor { } @Override public void onClosed(IBinder token) { public void onClosed(ComputerControlSessionImpl session) { synchronized (mSessions) { if (!mSessions.remove(token)) { if (!mSessions.remove(session)) { // The session was already removed, which can happen if close() is called // multiple times. return; Loading services/tests/servicestests/src/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessorTest.java +25 −3 Original line number Diff line number Diff line Loading @@ -157,14 +157,14 @@ public class ComputerControlSessionProcessorTest { try { for (int i = 0; i < MAXIMUM_CONCURRENT_SESSIONS; ++i) { mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); generateUniqueParams(i), mComputerControlSessionCallback); } verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS).times(MAXIMUM_CONCURRENT_SESSIONS)) .onSessionCreated(anyInt(), any(), mSessionArgumentCaptor.capture()); mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); generateUniqueParams(-1), mComputerControlSessionCallback); verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS)) .onSessionCreationFailed(ComputerControlSession.ERROR_SESSION_LIMIT_REACHED); Loading @@ -175,7 +175,7 @@ public class ComputerControlSessionProcessorTest { verify(mComputerControlSessionCallback, times(1)).onSessionClosed(); mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); generateUniqueParams(-1), mComputerControlSessionCallback); verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS).times(MAXIMUM_CONCURRENT_SESSIONS + 1)) .onSessionCreated(anyInt(), any(), mSessionArgumentCaptor.capture()); Loading Loading @@ -224,6 +224,17 @@ public class ComputerControlSessionProcessorTest { .onSessionCreationFailed(ComputerControlSession.ERROR_PERMISSION_DENIED); } @Test public void validateParams_sessionNameMustBeUnique() throws Exception { mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS)) .onSessionCreated(anyInt(), any(), any()); assertThrows(IllegalArgumentException.class, () -> mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback)); } @EnableFlags(Flags.FLAG_COMPUTER_CONTROL_ACTIVITY_POLICY_STRICT) @Test public void validateParams_packageNamesAreValid() throws Exception { Loading Loading @@ -276,4 +287,15 @@ public class ComputerControlSessionProcessorTest { params, mComputerControlSessionCallback); }); } private ComputerControlSessionParams generateUniqueParams(int index) { return new ComputerControlSessionParams.Builder() .setName(mParams.getName() + index) .setDisplayDpi(mParams.getDisplayDpi()) .setDisplayHeightPx(mParams.getDisplayHeightPx()) .setDisplayWidthPx(mParams.getDisplayWidthPx()) .setDisplaySurface(mParams.getDisplaySurface()) .setDisplayAlwaysUnlocked(mParams.isDisplayAlwaysUnlocked()) .build(); } } services/tests/servicestests/src/com/android/server/companion/virtual/computercontrol/ComputerControlSessionTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ public class ComputerControlSessionTest { createComputerControlSession(mDefaultParams); mSession.close(); verify(mVirtualDevice).close(); verify(mOnClosedListener).onClosed(mSession.asBinder()); verify(mOnClosedListener).onClosed(mSession); } @Test Loading Loading
services/companion/java/com/android/server/companion/virtual/computercontrol/ComputerControlSessionImpl.java +18 −5 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub private final IBinder mAppToken; private final ComputerControlSessionParams mParams; private final String mOwnerPackageName; private final OnClosedListener mOnClosedListener; private final IVirtualDevice mVirtualDevice; private final int mVirtualDisplayId; Loading @@ -120,6 +121,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub OnClosedListener onClosedListener, Injector injector) { mAppToken = appToken; mParams = params; mOwnerPackageName = attributionSource.getPackageName(); mOnClosedListener = onClosedListener; mInjector = injector; Loading Loading @@ -184,7 +186,10 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub mVirtualDevice.setDisplayImePolicy( mVirtualDisplayId, WindowManager.DISPLAY_IME_POLICY_HIDE); final String dpadName = mParams.getName() + "-dpad"; final String inputDeviceNamePrefix = attributionSource.getPackageName() + ":" + mParams.getName(); final String dpadName = inputDeviceNamePrefix + "-dpad"; final VirtualDpadConfig virtualDpadConfig = new VirtualDpadConfig.Builder() .setAssociatedDisplayId(mVirtualDisplayId) Loading @@ -193,7 +198,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub mVirtualDpad = mVirtualDevice.createVirtualDpad( virtualDpadConfig, new Binder(dpadName)); final String keyboardName = mParams.getName() + "-keyboard"; final String keyboardName = inputDeviceNamePrefix + "-keyboard"; final VirtualKeyboardConfig virtualKeyboardConfig = new VirtualKeyboardConfig.Builder() .setAssociatedDisplayId(mVirtualDisplayId) Loading @@ -202,7 +207,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub mVirtualKeyboard = mVirtualDevice.createVirtualKeyboard( virtualKeyboardConfig, new Binder(keyboardName)); final String touchscreenName = mParams.getName() + "-touchscreen"; final String touchscreenName = inputDeviceNamePrefix + "-touchscreen"; final VirtualTouchscreenConfig virtualTouchscreenConfig = new VirtualTouchscreenConfig.Builder(mDisplayWidth, mDisplayHeight) .setAssociatedDisplayId(mVirtualDisplayId) Loading Loading @@ -252,6 +257,14 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub return mVirtualDisplayToken; } String getName() { return mParams.getName(); } String getOwnerPackageName() { return mOwnerPackageName; } public void launchApplication(@NonNull String packageName) { if (!mParams.getTargetPackageNames().contains(Objects.requireNonNull(packageName))) { throw new IllegalArgumentException( Loading Loading @@ -360,7 +373,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub public void close() throws RemoteException { mVirtualDevice.close(); mAppToken.unlinkToDeath(this, 0); mOnClosedListener.onClosed(asBinder()); mOnClosedListener.onClosed(this); } @Override Loading Loading @@ -458,7 +471,7 @@ final class ComputerControlSessionImpl extends IComputerControlSession.Stub /** Interface for listening for closing of sessions. */ interface OnClosedListener { void onClosed(IBinder token); void onClosed(ComputerControlSessionImpl session); } @VisibleForTesting Loading
services/companion/java/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessor.java +20 −6 Original line number Diff line number Diff line Loading @@ -54,6 +54,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.ServiceThread; import java.util.Objects; /** * Handles creation and lifecycle of {@link ComputerControlSession}s. * Loading @@ -76,7 +78,7 @@ public class ComputerControlSessionProcessor { private final PendingIntentFactory mPendingIntentFactory; /** The binders of all currently active sessions. */ private final ArraySet<IBinder> mSessions = new ArraySet<>(); private final ArraySet<ComputerControlSessionImpl> mSessions = new ArraySet<>(); private final Object mHandlerThreadLock = new Object(); @GuardedBy("mHandlerThreadLock") Loading Loading @@ -111,7 +113,7 @@ public class ComputerControlSessionProcessor { @NonNull AttributionSource attributionSource, @NonNull ComputerControlSessionParams params, @NonNull IComputerControlSessionCallback callback) { validateParams(params); validateParams(attributionSource, params); startHandlerThreadIfNeeded(); final boolean canCreateWithoutConsent; Loading Loading @@ -150,7 +152,19 @@ public class ComputerControlSessionProcessor { } } private void validateParams(ComputerControlSessionParams params) { private void validateParams(AttributionSource attributionSource, ComputerControlSessionParams params) { synchronized (mSessions) { for (int i = 0; i < mSessions.size(); i++) { ComputerControlSessionImpl session = mSessions.valueAt(i); if (Objects.equals(attributionSource.getPackageName(), session.getOwnerPackageName()) && Objects.equals(params.getName(), session.getName())) { throw new IllegalArgumentException("Session name must be unique"); } } } if (!Flags.computerControlActivityPolicyStrict()) { return; } Loading Loading @@ -207,7 +221,7 @@ public class ComputerControlSessionProcessor { callback.asBinder(), params, attributionSource, mVirtualDeviceFactory, new OnSessionClosedListener(params.getName(), callback), new ComputerControlSessionImpl.Injector(mContext)); mSessions.add(session.asBinder()); mSessions.add(session); } // If the client provided a surface, disable the screenshot API. Loading Loading @@ -321,9 +335,9 @@ public class ComputerControlSessionProcessor { } @Override public void onClosed(IBinder token) { public void onClosed(ComputerControlSessionImpl session) { synchronized (mSessions) { if (!mSessions.remove(token)) { if (!mSessions.remove(session)) { // The session was already removed, which can happen if close() is called // multiple times. return; Loading
services/tests/servicestests/src/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessorTest.java +25 −3 Original line number Diff line number Diff line Loading @@ -157,14 +157,14 @@ public class ComputerControlSessionProcessorTest { try { for (int i = 0; i < MAXIMUM_CONCURRENT_SESSIONS; ++i) { mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); generateUniqueParams(i), mComputerControlSessionCallback); } verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS).times(MAXIMUM_CONCURRENT_SESSIONS)) .onSessionCreated(anyInt(), any(), mSessionArgumentCaptor.capture()); mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); generateUniqueParams(-1), mComputerControlSessionCallback); verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS)) .onSessionCreationFailed(ComputerControlSession.ERROR_SESSION_LIMIT_REACHED); Loading @@ -175,7 +175,7 @@ public class ComputerControlSessionProcessorTest { verify(mComputerControlSessionCallback, times(1)).onSessionClosed(); mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); generateUniqueParams(-1), mComputerControlSessionCallback); verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS).times(MAXIMUM_CONCURRENT_SESSIONS + 1)) .onSessionCreated(anyInt(), any(), mSessionArgumentCaptor.capture()); Loading Loading @@ -224,6 +224,17 @@ public class ComputerControlSessionProcessorTest { .onSessionCreationFailed(ComputerControlSession.ERROR_PERMISSION_DENIED); } @Test public void validateParams_sessionNameMustBeUnique() throws Exception { mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); verify(mComputerControlSessionCallback, timeout(CALLBACK_TIMEOUT_MS)) .onSessionCreated(anyInt(), any(), any()); assertThrows(IllegalArgumentException.class, () -> mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback)); } @EnableFlags(Flags.FLAG_COMPUTER_CONTROL_ACTIVITY_POLICY_STRICT) @Test public void validateParams_packageNamesAreValid() throws Exception { Loading Loading @@ -276,4 +287,15 @@ public class ComputerControlSessionProcessorTest { params, mComputerControlSessionCallback); }); } private ComputerControlSessionParams generateUniqueParams(int index) { return new ComputerControlSessionParams.Builder() .setName(mParams.getName() + index) .setDisplayDpi(mParams.getDisplayDpi()) .setDisplayHeightPx(mParams.getDisplayHeightPx()) .setDisplayWidthPx(mParams.getDisplayWidthPx()) .setDisplaySurface(mParams.getDisplaySurface()) .setDisplayAlwaysUnlocked(mParams.isDisplayAlwaysUnlocked()) .build(); } }
services/tests/servicestests/src/com/android/server/companion/virtual/computercontrol/ComputerControlSessionTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ public class ComputerControlSessionTest { createComputerControlSession(mDefaultParams); mSession.close(); verify(mVirtualDevice).close(); verify(mOnClosedListener).onClosed(mSession.asBinder()); verify(mOnClosedListener).onClosed(mSession); } @Test Loading