Merge "Avoid NPE on ScrollCaptureConnection callbacks" into tm-dev am: 6678f5566b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18463432

Change-Id: I1b1bb775f98d5fcdd4e3811b8917fb7f5e232dce
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-05-19 07:59:59 +00:00
committed by Automerger Merge Worker
2 changed files with 76 additions and 4 deletions

View File

@@ -144,8 +144,13 @@ public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub imple
Consumer<Rect> listener =
SafeCallback.create(mCancellation, mUiThread, this::onImageRequestCompleted);
// -> UiThread
mUiThread.execute(() -> mLocal.onScrollCaptureImageRequest(
mSession, mCancellation, new Rect(requestRect), listener));
mUiThread.execute(() -> {
if (mLocal != null) {
mLocal.onScrollCaptureImageRequest(
mSession, mCancellation, new Rect(requestRect), listener);
}
});
return cancellation;
}
@@ -174,7 +179,11 @@ public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub imple
Runnable listener =
SafeCallback.create(mCancellation, mUiThread, this::onEndCaptureCompleted);
// -> UiThread
mUiThread.execute(() -> mLocal.onScrollCaptureEnd(listener));
mUiThread.execute(() -> {
if (mLocal != null) {
mLocal.onScrollCaptureEnd(listener);
}
});
return cancellation;
}

View File

@@ -47,6 +47,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.Executor;
/**
* Tests of {@link ScrollCaptureConnection}.
*/
@@ -56,6 +60,7 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class ScrollCaptureConnectionTest {
private final Point mPositionInWindow = new Point(1, 2);
private final Rect mLocalVisibleRect = new Rect(2, 3, 4, 5);
private final Rect mScrollBounds = new Rect(3, 4, 5, 6);
@@ -73,6 +78,9 @@ public class ScrollCaptureConnectionTest {
private IScrollCaptureCallbacks mRemote;
@Mock
private View mView;
private FakeExecutor mFakeUiThread;
private final Executor mImmediateExecutor = Runnable::run;
@Before
public void setUp() {
@@ -84,7 +92,9 @@ public class ScrollCaptureConnectionTest {
mTarget = new ScrollCaptureTarget(mView, mLocalVisibleRect, mPositionInWindow, mCallback);
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 */
@@ -145,6 +155,21 @@ public class ScrollCaptureConnectionTest {
.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
public void testRequestImage_cancellation() throws Exception {
mConnection.startCapture(mSurface, mRemote);
@@ -176,6 +201,20 @@ public class ScrollCaptureConnectionTest {
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() */
@Test
public void testClose_withPendingOperation() throws Exception {
@@ -229,4 +268,28 @@ public class ScrollCaptureConnectionTest {
assertFalse(mConnection.isActive());
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();
}
}
}
}