Merge "Avoid NPE on ScrollCaptureConnection callbacks" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6678f5566b
@@ -144,8 +144,13 @@ public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub imple
|
|||||||
Consumer<Rect> listener =
|
Consumer<Rect> listener =
|
||||||
SafeCallback.create(mCancellation, mUiThread, this::onImageRequestCompleted);
|
SafeCallback.create(mCancellation, mUiThread, this::onImageRequestCompleted);
|
||||||
// -> UiThread
|
// -> UiThread
|
||||||
mUiThread.execute(() -> mLocal.onScrollCaptureImageRequest(
|
mUiThread.execute(() -> {
|
||||||
mSession, mCancellation, new Rect(requestRect), listener));
|
if (mLocal != null) {
|
||||||
|
mLocal.onScrollCaptureImageRequest(
|
||||||
|
mSession, mCancellation, new Rect(requestRect), listener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return cancellation;
|
return cancellation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +179,11 @@ public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub imple
|
|||||||
Runnable listener =
|
Runnable listener =
|
||||||
SafeCallback.create(mCancellation, mUiThread, this::onEndCaptureCompleted);
|
SafeCallback.create(mCancellation, mUiThread, this::onEndCaptureCompleted);
|
||||||
// -> UiThread
|
// -> UiThread
|
||||||
mUiThread.execute(() -> mLocal.onScrollCaptureEnd(listener));
|
mUiThread.execute(() -> {
|
||||||
|
if (mLocal != null) {
|
||||||
|
mLocal.onScrollCaptureEnd(listener);
|
||||||
|
}
|
||||||
|
});
|
||||||
return cancellation;
|
return cancellation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests of {@link ScrollCaptureConnection}.
|
* Tests of {@link ScrollCaptureConnection}.
|
||||||
*/
|
*/
|
||||||
@@ -56,6 +60,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class ScrollCaptureConnectionTest {
|
public class ScrollCaptureConnectionTest {
|
||||||
|
|
||||||
|
|
||||||
private final Point mPositionInWindow = new Point(1, 2);
|
private final Point mPositionInWindow = new Point(1, 2);
|
||||||
private final Rect mLocalVisibleRect = new Rect(2, 3, 4, 5);
|
private final Rect mLocalVisibleRect = new Rect(2, 3, 4, 5);
|
||||||
private final Rect mScrollBounds = new Rect(3, 4, 5, 6);
|
private final Rect mScrollBounds = new Rect(3, 4, 5, 6);
|
||||||
@@ -73,6 +78,9 @@ public class ScrollCaptureConnectionTest {
|
|||||||
private IScrollCaptureCallbacks mRemote;
|
private IScrollCaptureCallbacks mRemote;
|
||||||
@Mock
|
@Mock
|
||||||
private View mView;
|
private View mView;
|
||||||
|
private FakeExecutor mFakeUiThread;
|
||||||
|
|
||||||
|
private final Executor mImmediateExecutor = Runnable::run;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -84,7 +92,9 @@ public class ScrollCaptureConnectionTest {
|
|||||||
|
|
||||||
mTarget = new ScrollCaptureTarget(mView, mLocalVisibleRect, mPositionInWindow, mCallback);
|
mTarget = new ScrollCaptureTarget(mView, mLocalVisibleRect, mPositionInWindow, mCallback);
|
||||||
mTarget.setScrollBounds(mScrollBounds);
|
mTarget.setScrollBounds(mScrollBounds);
|
||||||
mConnection = new ScrollCaptureConnection(Runnable::run, mTarget);
|
mFakeUiThread = new FakeExecutor();
|
||||||
|
mFakeUiThread.setImmediate(true);
|
||||||
|
mConnection = new ScrollCaptureConnection(mFakeUiThread, mTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test creating a client with valid info */
|
/** Test creating a client with valid info */
|
||||||
@@ -145,6 +155,21 @@ public class ScrollCaptureConnectionTest {
|
|||||||
.onImageRequestCompleted(eq(0), eq(new Rect(1, 2, 3, 4)));
|
.onImageRequestCompleted(eq(0), eq(new Rect(1, 2, 3, 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Test closing while callbacks are in-flight: b/232375183 */
|
||||||
|
@Test
|
||||||
|
public void testRequestImage_afterClose() throws Exception {
|
||||||
|
mConnection = new ScrollCaptureConnection(mFakeUiThread, mTarget);
|
||||||
|
mConnection.startCapture(mSurface, mRemote);
|
||||||
|
mCallback.completeStartRequest();
|
||||||
|
|
||||||
|
mFakeUiThread.setImmediate(false);
|
||||||
|
mConnection.requestImage(new Rect(1, 2, 3, 4));
|
||||||
|
|
||||||
|
// Now close connection, before the UI thread executes
|
||||||
|
mConnection.close();
|
||||||
|
mFakeUiThread.runAll();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRequestImage_cancellation() throws Exception {
|
public void testRequestImage_cancellation() throws Exception {
|
||||||
mConnection.startCapture(mSurface, mRemote);
|
mConnection.startCapture(mSurface, mRemote);
|
||||||
@@ -176,6 +201,20 @@ public class ScrollCaptureConnectionTest {
|
|||||||
assertFalse(mConnection.isConnected());
|
assertFalse(mConnection.isConnected());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Test closing while callbacks are in-flight: b/232375183 */
|
||||||
|
@Test
|
||||||
|
public void testEndCapture_afterClose() throws Exception {
|
||||||
|
mConnection.startCapture(mSurface, mRemote);
|
||||||
|
mCallback.completeStartRequest();
|
||||||
|
|
||||||
|
mFakeUiThread.setImmediate(false);
|
||||||
|
mConnection.endCapture();
|
||||||
|
|
||||||
|
// Now close connection, before the UI thread executes
|
||||||
|
mConnection.close();
|
||||||
|
mFakeUiThread.runAll();
|
||||||
|
}
|
||||||
|
|
||||||
/** @see ScrollCaptureConnection#endCapture() */
|
/** @see ScrollCaptureConnection#endCapture() */
|
||||||
@Test
|
@Test
|
||||||
public void testClose_withPendingOperation() throws Exception {
|
public void testClose_withPendingOperation() throws Exception {
|
||||||
@@ -229,4 +268,28 @@ public class ScrollCaptureConnectionTest {
|
|||||||
assertFalse(mConnection.isActive());
|
assertFalse(mConnection.isActive());
|
||||||
assertFalse(mConnection.isConnected());
|
assertFalse(mConnection.isConnected());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class FakeExecutor implements Executor {
|
||||||
|
private Queue<Runnable> mQueue = new ArrayDeque<>();
|
||||||
|
private boolean mImmediate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
if (mImmediate) {
|
||||||
|
command.run();
|
||||||
|
} else {
|
||||||
|
mQueue.add(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImmediate(boolean immediate) {
|
||||||
|
mImmediate = immediate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runAll() {
|
||||||
|
while (!mQueue.isEmpty()) {
|
||||||
|
mQueue.remove().run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user