Test binder callbacks
Make sure that the VM can asynchronously call back to the app, and vice versa. This is mostly to ensure that all the necessary thread pools exist. While I'm here, suppress one AIDL warning, and promote any new ones to errors. Bug: 268335700 Test: atest MicrodroidTests Change-Id: I6b6d957f6e5d645e76eeee0454843debe6af7730
This commit is contained in:
parent
91b5a5976e
commit
63fa37b581
|
@ -6,6 +6,10 @@ aidl_interface {
|
|||
name: "com.android.microdroid.testservice",
|
||||
srcs: ["com/android/microdroid/testservice/**/*.aidl"],
|
||||
unstable: true,
|
||||
flags: [
|
||||
"-Werror",
|
||||
"-Wno-mixed-oneway",
|
||||
],
|
||||
backend: {
|
||||
java: {
|
||||
gen_rpc: true,
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.microdroid.testservice;
|
||||
|
||||
import com.android.microdroid.testservice.IVmCallback;
|
||||
|
||||
/**
|
||||
* An interface exposed by the app for callbacks from the VM.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IAppCallback {
|
||||
/** Invites the app to call vmCallback#echoMessage() */
|
||||
void setVmCallback(IVmCallback vmCallback);
|
||||
|
||||
/** Asynchronusly called by the VM in response to a call to echoMessage(). */
|
||||
void onEchoRequestReceived(String message);
|
||||
}
|
|
@ -15,7 +15,12 @@
|
|||
*/
|
||||
package com.android.microdroid.testservice;
|
||||
|
||||
/** {@hide} */
|
||||
import com.android.microdroid.testservice.IAppCallback;
|
||||
|
||||
/**
|
||||
* This is the service exposed by the test payload, called by the test app.
|
||||
* {@hide}
|
||||
*/
|
||||
interface ITestService {
|
||||
const long SERVICE_PORT = 5678;
|
||||
|
||||
|
@ -62,6 +67,9 @@ interface ITestService {
|
|||
/** Returns flags for the given mountPoint. */
|
||||
int getMountFlags(String mountPoint);
|
||||
|
||||
/** Requests the VM to asynchronously call appCallback.setVmCallback() */
|
||||
void requestCallback(IAppCallback appCallback);
|
||||
|
||||
/**
|
||||
* Request the service to exit, triggering the termination of the VM. This may cause any
|
||||
* requests in flight to fail.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.microdroid.testservice;
|
||||
|
||||
/**
|
||||
* An interface exposed by the VM for callbacks from the app.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IVmCallback {
|
||||
/** Requests the VM to asynchronously call the app's onEchoRequestReceived() callback. */
|
||||
void echoMessage(String message);
|
||||
}
|
|
@ -58,7 +58,9 @@ import android.util.Log;
|
|||
import com.android.compatibility.common.util.CddTest;
|
||||
import com.android.microdroid.test.device.MicrodroidDeviceTestBase;
|
||||
import com.android.microdroid.test.vmshare.IVmShareTestService;
|
||||
import com.android.microdroid.testservice.IAppCallback;
|
||||
import com.android.microdroid.testservice.ITestService;
|
||||
import com.android.microdroid.testservice.IVmCallback;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
@ -399,6 +401,59 @@ public class MicrodroidTests extends MicrodroidDeviceTestBase {
|
|||
assertThat(response.get()).isEqualTo(new StringBuilder(request).reverse().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@CddTest(requirements = {"9.17/C-1-1"})
|
||||
public void binderCallbacksWork() throws Exception {
|
||||
assumeSupportedKernel();
|
||||
|
||||
VirtualMachineConfig config =
|
||||
newVmConfigBuilder()
|
||||
.setPayloadBinaryName("MicrodroidTestNativeLib.so")
|
||||
.setMemoryBytes(minMemoryRequired())
|
||||
.setDebugLevel(DEBUG_LEVEL_FULL)
|
||||
.build();
|
||||
VirtualMachine vm = forceCreateNewVirtualMachine("test_vm", config);
|
||||
|
||||
String request = "Hello";
|
||||
CompletableFuture<String> response = new CompletableFuture<>();
|
||||
|
||||
IAppCallback appCallback =
|
||||
new IAppCallback.Stub() {
|
||||
@Override
|
||||
public void setVmCallback(IVmCallback vmCallback) {
|
||||
// Do this on a separate thread to simulate an asynchronous trigger,
|
||||
// and to make sure it doesn't happen in the context of an inbound binder
|
||||
// call.
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
vmCallback.echoMessage(request);
|
||||
} catch (Exception e) {
|
||||
response.completeExceptionally(e);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEchoRequestReceived(String message) {
|
||||
response.complete(message);
|
||||
}
|
||||
};
|
||||
|
||||
TestResults testResults =
|
||||
runVmTestService(
|
||||
TAG,
|
||||
vm,
|
||||
(service, results) -> {
|
||||
service.requestCallback(appCallback);
|
||||
response.get(10, TimeUnit.SECONDS);
|
||||
});
|
||||
testResults.assertNoException();
|
||||
assertThat(response.getNow("no response")).isEqualTo("Received: " + request);
|
||||
}
|
||||
|
||||
@Test
|
||||
@CddTest(requirements = {"9.17/C-1-1"})
|
||||
public void vmConfigGetAndSetTests() {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
|
||||
#include <aidl/com/android/microdroid/testservice/BnTestService.h>
|
||||
#include <aidl/com/android/microdroid/testservice/BnVmCallback.h>
|
||||
#include <aidl/com/android/microdroid/testservice/IAppCallback.h>
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/result.h>
|
||||
|
@ -47,6 +49,8 @@ using android::fs_mgr::GetEntryForMountPoint;
|
|||
using android::fs_mgr::ReadFstabFromFile;
|
||||
|
||||
using aidl::com::android::microdroid::testservice::BnTestService;
|
||||
using aidl::com::android::microdroid::testservice::BnVmCallback;
|
||||
using aidl::com::android::microdroid::testservice::IAppCallback;
|
||||
using ndk::ScopedAStatus;
|
||||
|
||||
extern void testlib_sub();
|
||||
|
@ -144,7 +148,25 @@ Result<void> start_echo_reverse_server() {
|
|||
}
|
||||
|
||||
Result<void> start_test_service() {
|
||||
class VmCallbackImpl : public BnVmCallback {
|
||||
private:
|
||||
std::shared_ptr<IAppCallback> mAppCallback;
|
||||
|
||||
public:
|
||||
explicit VmCallbackImpl(const std::shared_ptr<IAppCallback>& appCallback)
|
||||
: mAppCallback(appCallback) {}
|
||||
|
||||
ScopedAStatus echoMessage(const std::string& message) override {
|
||||
std::thread callback_thread{[=, appCallback = mAppCallback] {
|
||||
appCallback->onEchoRequestReceived("Received: " + message);
|
||||
}};
|
||||
callback_thread.detach();
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
};
|
||||
|
||||
class TestService : public BnTestService {
|
||||
public:
|
||||
ScopedAStatus addInteger(int32_t a, int32_t b, int32_t* out) override {
|
||||
*out = a + b;
|
||||
return ScopedAStatus::ok();
|
||||
|
@ -226,7 +248,7 @@ Result<void> start_test_service() {
|
|||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
virtual ::ScopedAStatus runEchoReverseServer() override {
|
||||
ScopedAStatus runEchoReverseServer() override {
|
||||
auto result = start_echo_reverse_server();
|
||||
if (result.ok()) {
|
||||
return ScopedAStatus::ok();
|
||||
|
@ -284,6 +306,13 @@ Result<void> start_test_service() {
|
|||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus requestCallback(const std::shared_ptr<IAppCallback>& appCallback) {
|
||||
auto vmCallback = ndk::SharedRefBase::make<VmCallbackImpl>(appCallback);
|
||||
std::thread callback_thread{[=] { appCallback->setVmCallback(vmCallback); }};
|
||||
callback_thread.detach();
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus quit() override { exit(0); }
|
||||
};
|
||||
auto testService = ndk::SharedRefBase::make<TestService>();
|
||||
|
|
|
@ -29,6 +29,7 @@ import android.util.Log;
|
|||
|
||||
import com.android.microdroid.test.vmshare.IVmShareTestService;
|
||||
import com.android.microdroid.testservice.ITestService;
|
||||
import com.android.microdroid.testservice.IAppCallback;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -239,6 +240,11 @@ public class VmShareServiceImpl extends Service {
|
|||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestCallback(IAppCallback appCallback) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void quit() throws RemoteException {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
|
|
Loading…
Reference in New Issue