Loading core/java/android/companion/virtual/computercontrol/ComputerControlSession.java +13 −3 Original line number Diff line number Diff line Loading @@ -51,11 +51,21 @@ public final class ComputerControlSession implements AutoCloseable { */ public static final int ERROR_SESSION_LIMIT_REACHED = -1; /** * Error code indicating that a new session cannot be created because the lock screen (also * known as Keyguard) is showing. * * <p>This is a transient error and the session creation request can be retried later.</p> * * @see android.app.KeyguardManager#isKeyguardLocked() */ public static final int ERROR_KEYGUARD_LOCKED = -2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( prefix = "ERROR_", value = {ERROR_SESSION_LIMIT_REACHED}) @IntDef(prefix = "ERROR_", value = { ERROR_SESSION_LIMIT_REACHED, ERROR_KEYGUARD_LOCKED}) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface SessionCreationError { } Loading services/companion/java/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessor.java +20 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.companion.virtual.computercontrol; import android.annotation.NonNull; import android.app.KeyguardManager; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.VirtualDeviceParams; Loading Loading @@ -45,6 +46,7 @@ public class ComputerControlSessionProcessor { static final int MAXIMUM_CONCURRENT_SESSIONS = 5; private final PackageManager mPackageManager; private final KeyguardManager mKeyguardManager; private final VirtualDeviceFactory mVirtualDeviceFactory; private final WindowManagerInternal mWindowManagerInternal; private final ArraySet<IBinder> mSessions = new ArraySet<>(); Loading @@ -53,6 +55,7 @@ public class ComputerControlSessionProcessor { Context context, VirtualDeviceFactory virtualDeviceFactory) { mVirtualDeviceFactory = virtualDeviceFactory; mPackageManager = context.getPackageManager(); mKeyguardManager = context.getSystemService(KeyguardManager.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); } Loading @@ -63,15 +66,15 @@ public class ComputerControlSessionProcessor { @NonNull AttributionSource attributionSource, @NonNull ComputerControlSessionParams params, @NonNull IComputerControlSessionCallback callback) { if (mKeyguardManager.isKeyguardLocked()) { dispatchSessionCreationFailed( callback, params, ComputerControlSession.ERROR_KEYGUARD_LOCKED); return; } synchronized (mSessions) { if (mSessions.size() >= MAXIMUM_CONCURRENT_SESSIONS) { try { callback.onSessionCreationFailed( ComputerControlSession.ERROR_SESSION_LIMIT_REACHED); } catch (RemoteException e) { Slog.e(TAG, "Failed to notify ComputerControlSession " + params.getName() + " about session creation failure"); } dispatchSessionCreationFailed( callback, params, ComputerControlSession.ERROR_SESSION_LIMIT_REACHED); return; } IComputerControlSession session = new ComputerControlSessionImpl( Loading @@ -88,6 +91,16 @@ public class ComputerControlSessionProcessor { } } private void dispatchSessionCreationFailed(IComputerControlSessionCallback callback, ComputerControlSessionParams params, int reason) { try { callback.onSessionCreationFailed(reason); } catch (RemoteException e) { Slog.e(TAG, "Failed to notify ComputerControlSession " + params.getName() + " about session creation failure"); } } private class OnSessionClosedListener implements ComputerControlSessionImpl.OnClosedListener { private final String mSessionName; private final IComputerControlSessionCallback mAppCallback; Loading services/tests/servicestests/src/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessorTest.java +20 −2 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.server.companion.virtual.computercontrol; import static com.android.server.companion.virtual.computercontrol.ComputerControlSessionProcessor.MAXIMUM_CONCURRENT_SESSIONS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.computercontrol.ComputerControlSession; import android.companion.virtual.computercontrol.ComputerControlSessionParams; Loading @@ -30,6 +32,7 @@ import android.companion.virtual.computercontrol.IComputerControlSession; import android.companion.virtual.computercontrol.IComputerControlSessionCallback; import android.content.AttributionSource; import android.content.Context; import android.content.ContextWrapper; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.Surface; Loading @@ -53,6 +56,8 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class ComputerControlSessionProcessorTest { @Mock private KeyguardManager mKeyguardManager; @Mock private WindowManagerInternal mWindowManagerInternal; @Mock Loading @@ -73,8 +78,7 @@ public class ComputerControlSessionProcessorTest { .setDisplayAlwaysUnlocked(true) .build(); private final Context mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); private Context mContext; private ComputerControlSessionProcessor mProcessor; private AutoCloseable mMockitoSession; Loading @@ -86,6 +90,10 @@ public class ComputerControlSessionProcessorTest { LocalServices.removeServiceForTest(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); when(mContext.getSystemService(Context.KEYGUARD_SERVICE)).thenReturn(mKeyguardManager); when(mVirtualDeviceFactory.createVirtualDevice(any(), any(), any(), any())) .thenReturn(mVirtualDevice); when(mComputerControlSessionCallback.asBinder()).thenReturn(new Binder()); Loading @@ -97,6 +105,16 @@ public class ComputerControlSessionProcessorTest { mMockitoSession.close(); } @Test public void keyguardLocked_sessionNotCreated() throws Exception { when(mKeyguardManager.isKeyguardLocked()).thenReturn(true); mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); verify(mComputerControlSessionCallback) .onSessionCreationFailed(ComputerControlSession.ERROR_KEYGUARD_LOCKED); } @Test public void maximumNumberOfSessions_isEnforced() throws Exception { try { Loading Loading
core/java/android/companion/virtual/computercontrol/ComputerControlSession.java +13 −3 Original line number Diff line number Diff line Loading @@ -51,11 +51,21 @@ public final class ComputerControlSession implements AutoCloseable { */ public static final int ERROR_SESSION_LIMIT_REACHED = -1; /** * Error code indicating that a new session cannot be created because the lock screen (also * known as Keyguard) is showing. * * <p>This is a transient error and the session creation request can be retried later.</p> * * @see android.app.KeyguardManager#isKeyguardLocked() */ public static final int ERROR_KEYGUARD_LOCKED = -2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( prefix = "ERROR_", value = {ERROR_SESSION_LIMIT_REACHED}) @IntDef(prefix = "ERROR_", value = { ERROR_SESSION_LIMIT_REACHED, ERROR_KEYGUARD_LOCKED}) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface SessionCreationError { } Loading
services/companion/java/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessor.java +20 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.companion.virtual.computercontrol; import android.annotation.NonNull; import android.app.KeyguardManager; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; import android.companion.virtual.VirtualDeviceParams; Loading Loading @@ -45,6 +46,7 @@ public class ComputerControlSessionProcessor { static final int MAXIMUM_CONCURRENT_SESSIONS = 5; private final PackageManager mPackageManager; private final KeyguardManager mKeyguardManager; private final VirtualDeviceFactory mVirtualDeviceFactory; private final WindowManagerInternal mWindowManagerInternal; private final ArraySet<IBinder> mSessions = new ArraySet<>(); Loading @@ -53,6 +55,7 @@ public class ComputerControlSessionProcessor { Context context, VirtualDeviceFactory virtualDeviceFactory) { mVirtualDeviceFactory = virtualDeviceFactory; mPackageManager = context.getPackageManager(); mKeyguardManager = context.getSystemService(KeyguardManager.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); } Loading @@ -63,15 +66,15 @@ public class ComputerControlSessionProcessor { @NonNull AttributionSource attributionSource, @NonNull ComputerControlSessionParams params, @NonNull IComputerControlSessionCallback callback) { if (mKeyguardManager.isKeyguardLocked()) { dispatchSessionCreationFailed( callback, params, ComputerControlSession.ERROR_KEYGUARD_LOCKED); return; } synchronized (mSessions) { if (mSessions.size() >= MAXIMUM_CONCURRENT_SESSIONS) { try { callback.onSessionCreationFailed( ComputerControlSession.ERROR_SESSION_LIMIT_REACHED); } catch (RemoteException e) { Slog.e(TAG, "Failed to notify ComputerControlSession " + params.getName() + " about session creation failure"); } dispatchSessionCreationFailed( callback, params, ComputerControlSession.ERROR_SESSION_LIMIT_REACHED); return; } IComputerControlSession session = new ComputerControlSessionImpl( Loading @@ -88,6 +91,16 @@ public class ComputerControlSessionProcessor { } } private void dispatchSessionCreationFailed(IComputerControlSessionCallback callback, ComputerControlSessionParams params, int reason) { try { callback.onSessionCreationFailed(reason); } catch (RemoteException e) { Slog.e(TAG, "Failed to notify ComputerControlSession " + params.getName() + " about session creation failure"); } } private class OnSessionClosedListener implements ComputerControlSessionImpl.OnClosedListener { private final String mSessionName; private final IComputerControlSessionCallback mAppCallback; Loading
services/tests/servicestests/src/com/android/server/companion/virtual/computercontrol/ComputerControlSessionProcessorTest.java +20 −2 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.server.companion.virtual.computercontrol; import static com.android.server.companion.virtual.computercontrol.ComputerControlSessionProcessor.MAXIMUM_CONCURRENT_SESSIONS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.computercontrol.ComputerControlSession; import android.companion.virtual.computercontrol.ComputerControlSessionParams; Loading @@ -30,6 +32,7 @@ import android.companion.virtual.computercontrol.IComputerControlSession; import android.companion.virtual.computercontrol.IComputerControlSessionCallback; import android.content.AttributionSource; import android.content.Context; import android.content.ContextWrapper; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.Surface; Loading @@ -53,6 +56,8 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class ComputerControlSessionProcessorTest { @Mock private KeyguardManager mKeyguardManager; @Mock private WindowManagerInternal mWindowManagerInternal; @Mock Loading @@ -73,8 +78,7 @@ public class ComputerControlSessionProcessorTest { .setDisplayAlwaysUnlocked(true) .build(); private final Context mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); private Context mContext; private ComputerControlSessionProcessor mProcessor; private AutoCloseable mMockitoSession; Loading @@ -86,6 +90,10 @@ public class ComputerControlSessionProcessorTest { LocalServices.removeServiceForTest(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); when(mContext.getSystemService(Context.KEYGUARD_SERVICE)).thenReturn(mKeyguardManager); when(mVirtualDeviceFactory.createVirtualDevice(any(), any(), any(), any())) .thenReturn(mVirtualDevice); when(mComputerControlSessionCallback.asBinder()).thenReturn(new Binder()); Loading @@ -97,6 +105,16 @@ public class ComputerControlSessionProcessorTest { mMockitoSession.close(); } @Test public void keyguardLocked_sessionNotCreated() throws Exception { when(mKeyguardManager.isKeyguardLocked()).thenReturn(true); mProcessor.processNewSessionRequest(AttributionSource.myAttributionSource(), mParams, mComputerControlSessionCallback); verify(mComputerControlSessionCallback) .onSessionCreationFailed(ComputerControlSession.ERROR_KEYGUARD_LOCKED); } @Test public void maximumNumberOfSessions_isEnforced() throws Exception { try { Loading