Merge changes I3294e35f,I2b3572d5 into main
* changes:
Support 'multi-touch' in trackpad
Support trackpad 'click'
diff --git a/dice_for_avf_guest.cddl b/dice_for_avf_guest.cddl
new file mode 100644
index 0000000..372ee15
--- /dev/null
+++ b/dice_for_avf_guest.cddl
@@ -0,0 +1,69 @@
+; DICE Specification for guest VM
+
+; See the Open DICE specification
+; https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md,
+; and the Android Profile for DICE
+; https://pigweed.googlesource.com/open-dice/+/HEAD/docs/android.md.
+
+; This CDDL describes the Configuration Descriptor used for components running in AVF Guest environment
+; (VM core components and payload). It extends the `ConfigurationDescriptor` specified at
+; https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
+
+; Additionally, we reserve range -71000...-71999 for AVF system specific usage. These are or can be
+; used by frameworks & parsers of DICE chains such as local and remote attestation frameworks.
+; Vendor must not use these key/values for other purposes, that may compromise the integrity of the system.
+; Note that each of the key-value pairs may not be useful for all the boot components and therefore
+; are optional. For e.g., SubcomponentDescriptor is only used in Microdroid payload, it may
+; not have immediate use for pVM firmware.
+
+; Each components of VM must specify the value corresponding to `Component name`(-70002).
+; For provided reference implementations:
+;
+; 1. "vm_entry" - Guest 'OS'. This is the payload booted by pVM firmware. For e.g, Microdroid, Rialto.
+; 2. "Microdroid vendor" - The vendor image, specific to Microdroid.
+; 3. "Microdroid Payload" - Payload run by Microdroid Manager.
+
+
+ConfigDescriptor = {
+ -70002 : tstr, ; Component name
+ (? -71000: tstr // ; Path to the payload config file
+ ? -71001: PayloadConfig),
+ ? -71002: [+ SubcomponentDescriptor], ; The order of these should be kept constant on each boot
+ ; of the VM instance
+ ? -71003: bstr .size 64 ; Instance hash: Unique identifier of the VM instance
+}
+
+PayloadConfig = {
+ 1: tstr ; Path to the binary file where payload execution starts
+}
+
+; Describes a unit of code (e.g. an APK or an APEX) present inside the VM.
+;
+; For an APK, the fields are as follows:
+; - Component name: The string "apk:" followed by the package name.
+; - Security version: The long version code from the APK manifest
+; (https://developer.android.com/reference/android/content/pm/PackageInfo#getLongVersionCode()).
+; - Code hash: This is the root hash of a Merkle tree computed over all bytes of the APK, as used
+; in the APK Signature Scheme v4 (https://source.android.com/docs/security/features/apksigning/v4)
+; with empty salt and using SHA-256 as the hash algorithm.
+; - Authority hash: The SHA-512 hash of the DER representation of the X.509 certificate for the
+; public key used to sign the APK.
+;
+; For an APEX, they are as follows:
+; - Component name: The string "apex:" followed by the APEX name as specified in the APEX Manifest
+; (see https://source.android.com/docs/core/ota/apex).
+; - Security version: The version number from the APEX Manifest.
+; - Code hash: The root hash of the apex_payload.img file within the APEX, taken from the first
+; hashtree descriptor in the VBMeta image
+; (see https://android.googlesource.com/platform/external/avb/+/master/README.md).
+; - Authority hash: The SHA-512 hash of the public key used to sign the file system image in the
+; APEX (as stored in the apex_pubkey file). The format is as described for AvbRSAPublicKeyHeader
+; in https://cs.android.com/android/platform/superproject/main/+/main:external/avb/libavb/avb_crypto.h.
+SubcomponentDescriptor = {
+ 1: tstr, ; Component name
+ 2: uint, ; Security version
+ 3: bstr, ; Code hash
+ 4: bstr, ; Authority hash
+}
+
+TODO: Describe how these descriptors are used by AVF components in Android W.
\ No newline at end of file
diff --git a/docs/updatable_vm.md b/docs/updatable_vm.md
index ff1a0d6..24c1b4b 100644
--- a/docs/updatable_vm.md
+++ b/docs/updatable_vm.md
@@ -59,8 +59,9 @@
1. GreaterOrEqual on SECURITY_VERSION: The secrets will be accessible if version of any
image is greater or equal to the set version.
- For each Subcomponent on the last DiceChainEntry (which corresponds to VM payload, See
- [vm_config.cddl][vm_config_cddl]): - GreaterOrEqual on SECURITY_VERSION - ExactMatch on
- AUTHORITY_HASH.
+ [dice_for_avf_guest.cddl][dice_for_avf_guest_cddl]):
+ - GreaterOrEqual on SECURITY_VERSION
+ - ExactMatch on AUTHORITY_HASH.
The sealing policy is updated each time the secret is retrieved. This ensures the secrets are only
released if the security version of the images are non-decreasing.
@@ -96,4 +97,4 @@
[open_dice_spec_cdi]: https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md#cdi-values
[secretkeeperhal]: https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
[sk_project]: https://android.googlesource.com/platform/system/secretkeeper/
-[vm_config_cddl]: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/microdroid_manager/src/vm_config.cddl
+[dice_for_avf_guest_cddl]: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/dice_for_avf_guest.cddl
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachine.java b/java/framework/src/android/system/virtualmachine/VirtualMachine.java
index d1321f0..1d64ee4 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachine.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachine.java
@@ -71,7 +71,6 @@
import android.system.virtualizationservice.IVirtualMachineCallback;
import android.system.virtualizationservice.IVirtualizationService;
import android.system.virtualizationservice.InputDevice;
-import android.system.virtualizationservice.MemoryTrimLevel;
import android.system.virtualizationservice.PartitionType;
import android.system.virtualizationservice.VirtualMachineAppConfig;
import android.system.virtualizationservice.VirtualMachineRawConfig;
@@ -270,34 +269,35 @@
@Override
public void onTrimMemory(int level) {
- @MemoryTrimLevel int vmTrimLevel;
+ int percent;
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
- vmTrimLevel = MemoryTrimLevel.TRIM_MEMORY_RUNNING_CRITICAL;
+ percent = 50;
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
- vmTrimLevel = MemoryTrimLevel.TRIM_MEMORY_RUNNING_LOW;
+ percent = 30;
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
- vmTrimLevel = MemoryTrimLevel.TRIM_MEMORY_RUNNING_MODERATE;
+ percent = 10;
break;
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
/* Release as much memory as we can. The app is on the LMKD LRU kill list. */
- vmTrimLevel = MemoryTrimLevel.TRIM_MEMORY_RUNNING_CRITICAL;
+ percent = 50;
break;
default:
/* Treat unrecognised messages as generic low-memory warnings. */
- vmTrimLevel = MemoryTrimLevel.TRIM_MEMORY_RUNNING_LOW;
+ percent = 30;
break;
}
synchronized (mLock) {
try {
if (mVirtualMachine != null) {
- mVirtualMachine.onTrimMemory(vmTrimLevel);
+ long bytes = mConfig.getMemoryBytes();
+ mVirtualMachine.setMemoryBalloon(bytes * percent / 100);
}
} catch (Exception e) {
/* Caller doesn't want our exceptions. Log them instead. */
diff --git a/libs/hypervisor_props/src/lib.rs b/libs/hypervisor_props/src/lib.rs
index 6665bc5..14614fd 100644
--- a/libs/hypervisor_props/src/lib.rs
+++ b/libs/hypervisor_props/src/lib.rs
@@ -37,8 +37,3 @@
pub fn version() -> Result<Option<String>> {
Ok(hypervisorproperties::hypervisor_version()?)
}
-
-/// Returns if the hypervisor is pKVM
-pub fn is_pkvm() -> Result<bool> {
- Ok(version()?.unwrap_or_default().starts_with("kvm") && is_protected_vm_supported()?)
-}
diff --git a/microdroid/derive_microdroid_vendor_dice_node/src/main.rs b/microdroid/derive_microdroid_vendor_dice_node/src/main.rs
index c7bc3f5..0f0631e 100644
--- a/microdroid/derive_microdroid_vendor_dice_node/src/main.rs
+++ b/microdroid/derive_microdroid_vendor_dice_node/src/main.rs
@@ -47,6 +47,7 @@
Path::new(AVF_STRICT_BOOT).exists()
}
+// See dice_for_avf_guest.cddl for CDDL of Configuration Descriptor of VM components.
fn build_descriptor(vbmeta: &VbMetaImage) -> Result<Vec<u8>> {
let values = DiceConfigValues {
component_name: Some(cstr!("Microdroid vendor")),
diff --git a/microdroid_manager/src/dice.rs b/microdroid_manager/src/dice.rs
index cecf413..7cfeb21 100644
--- a/microdroid_manager/src/dice.rs
+++ b/microdroid_manager/src/dice.rs
@@ -134,8 +134,8 @@
apks.chain(apexes).collect()
}
-// Returns a configuration descriptor of the given payload. See vm_config.cddl for the definition
-// of the format.
+// Returns a configuration descriptor of the given payload. See dice_for_avf_guest.cddl for the
+// definition of the format.
fn format_payload_config_descriptor(
payload: &PayloadMetadata,
subcomponents: Vec<Subcomponent>,
diff --git a/microdroid_manager/src/vm_config.cddl b/microdroid_manager/src/vm_config.cddl
deleted file mode 100644
index 8508e8f..0000000
--- a/microdroid_manager/src/vm_config.cddl
+++ /dev/null
@@ -1,56 +0,0 @@
-; Configuration Descriptor used in the DICE node that describes the payload of a Microdroid virtual
-; machine.
-;
-; See the Open DICE specification
-; https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md,
-; and the Android Profile for DICE
-; https://pigweed.googlesource.com/open-dice/+/HEAD/docs/android.md.
-;
-; CDDL for the normal Configuration Descriptor can be found at
-; https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
-
-; The configuration descriptor node for a Microdroid VM, with extensions to describe the contents
-; of the VM payload.
-; The subcomponents describe the APKs and then the APEXes that are part of the VM. The main APK
-; is first, followed by any extra APKs in the order they are specified in the VM config.
-; The APEXes are listed in the order specified when the VM is created, which is normally alphabetic
-; order by name.
-VmConfigDescriptor = {
- -70002 : "Microdroid payload", ; Component name
- (? -71000: tstr // ; Path to the payload config file
- ? -71001: PayloadConfig),
- ? -71002: [+ SubcomponentDescriptor],
-}
-
-PayloadConfig = {
- 1: tstr ; Path to the binary file where payload execution starts
-}
-
-; Describes a unit of code (e.g. an APK or an APEX) present inside the VM.
-;
-; For an APK, the fields are as follows:
-; - Component name: The string "apk:" followed by the package name.
-; - Security version: The long version code from the APK manifest
-; (https://developer.android.com/reference/android/content/pm/PackageInfo#getLongVersionCode()).
-; - Code hash: This is the root hash of a Merkle tree computed over all bytes of the APK, as used
-; in the APK Signature Scheme v4 (https://source.android.com/docs/security/features/apksigning/v4)
-; with empty salt and using SHA-256 as the hash algorithm.
-; - Authority hash: The SHA-512 hash of the DER representation of the X.509 certificate for the
-; public key used to sign the APK.
-;
-; For an APEX, they are as follows:
-; - Component name: The string "apex:" followed by the APEX name as specified in the APEX Manifest
-; (see https://source.android.com/docs/core/ota/apex).
-; - Security version: The version number from the APEX Manifest.
-; - Code hash: The root hash of the apex_payload.img file within the APEX, taken from the first
-; hashtree descriptor in the VBMeta image
-; (see https://android.googlesource.com/platform/external/avb/+/master/README.md).
-; - Authority hash: The SHA-512 hash of the public key used to sign the file system image in the
-; APEX (as stored in the apex_pubkey file). The format is as described for AvbRSAPublicKeyHeader
-; in https://cs.android.com/android/platform/superproject/main/+/main:external/avb/libavb/avb_crypto.h.
-SubcomponentDescriptor = {
- 1: tstr, ; Component name
- 2: uint, ; Security version
- 3: bstr, ; Code hash
- 4: bstr, ; Authority hash
-}
diff --git a/microdroid_manager/src/vm_secret.rs b/microdroid_manager/src/vm_secret.rs
index c16a45e..1ad2d88 100644
--- a/microdroid_manager/src/vm_secret.rs
+++ b/microdroid_manager/src/vm_secret.rs
@@ -171,7 +171,7 @@
// rollback protection of pvmfw. Such components may chose to not put SECURITY_VERSION in the
// corresponding DiceChainEntry.
// 4. For each Subcomponent on the last DiceChainEntry (which corresponds to VM payload, See
-// microdroid_manager/src/vm_config.cddl):
+// dice_for_avf_guest.cddl):
// - GreaterOrEqual on SECURITY_VERSION (Required)
// - ExactMatch on AUTHORITY_HASH (Required).
// 5. ExactMatch on Instance Hash (Required) - This uniquely identifies one VM instance from
diff --git a/pvmfw/src/dice.rs b/pvmfw/src/dice.rs
index da19931..8be73a4 100644
--- a/pvmfw/src/dice.rs
+++ b/pvmfw/src/dice.rs
@@ -26,10 +26,11 @@
use pvmfw_avb::{Capability, DebugLevel, Digest, VerifiedBootData};
use zerocopy::AsBytes;
+// pVM firmware (like other VM components) is expected to populate some fields in DICE
+// Configuration Descriptor. See dice_for_avf_guest.cddl
const COMPONENT_NAME_KEY: i64 = -70002;
const SECURITY_VERSION_KEY: i64 = -70005;
const RKP_VM_MARKER_KEY: i64 = -70006;
-// TODO(b/291245237): Document this key along with others used in ConfigDescriptor in AVF based VM.
const INSTANCE_HASH_KEY: i64 = -71003;
#[derive(Debug)]
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 425beed..2d83963 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -36,7 +36,6 @@
IVirtualMachine::{BnVirtualMachine, IVirtualMachine},
IVirtualMachineCallback::IVirtualMachineCallback,
IVirtualizationService::IVirtualizationService,
- MemoryTrimLevel::MemoryTrimLevel,
Partition::Partition,
PartitionType::PartitionType,
VirtualMachineAppConfig::{DebugLevel::DebugLevel, Payload::Payload, VirtualMachineAppConfig},
@@ -1234,10 +1233,20 @@
.or_service_specific_exception(-1)
}
- fn onTrimMemory(&self, level: MemoryTrimLevel) -> binder::Result<()> {
+ fn getMemoryBalloon(&self) -> binder::Result<i64> {
+ let balloon = self
+ .instance
+ .get_memory_balloon()
+ .with_context(|| format!("Error getting balloon for VM with CID {}", self.instance.cid))
+ .with_log()
+ .or_service_specific_exception(-1)?;
+ Ok(balloon.try_into().unwrap())
+ }
+
+ fn setMemoryBalloon(&self, num_bytes: i64) -> binder::Result<()> {
self.instance
- .trim_memory(level)
- .with_context(|| format!("Error trimming VM with CID {}", self.instance.cid))
+ .set_memory_balloon(num_bytes.try_into().unwrap())
+ .with_context(|| format!("Error setting balloon for VM with CID {}", self.instance.cid))
.with_log()
.or_service_specific_exception(-1)
}
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index 379a498..852d7de 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -44,7 +44,6 @@
use std::thread::{self, JoinHandle};
use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::DeathReason::DeathReason;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
- MemoryTrimLevel::MemoryTrimLevel,
VirtualMachineAppConfig::DebugLevel::DebugLevel,
AudioConfig::AudioConfig as AudioConfigParcelable,
DisplayConfig::DisplayConfig as DisplayConfigParcelable,
@@ -627,42 +626,35 @@
/// Responds to memory-trimming notifications by inflating the virtio
/// balloon to reclaim guest memory.
- pub fn trim_memory(&self, level: MemoryTrimLevel) -> Result<(), Error> {
+ pub fn get_memory_balloon(&self) -> Result<u64, Error> {
let request = VmRequest::BalloonCommand(BalloonControlCommand::Stats {});
- match vm_control::client::handle_request(&request, &self.crosvm_control_socket_path) {
- Ok(VmResponse::BalloonStats { stats, balloon_actual: _ }) => {
- if let Some(total_memory) = stats.total_memory {
- // Reclaim up to 50% of total memory assuming worst case
- // most memory is anonymous and must be swapped to zram
- // with an approximate 2:1 compression ratio.
- let pct = match level {
- MemoryTrimLevel::TRIM_MEMORY_RUNNING_CRITICAL => 50,
- MemoryTrimLevel::TRIM_MEMORY_RUNNING_LOW => 30,
- MemoryTrimLevel::TRIM_MEMORY_RUNNING_MODERATE => 10,
- _ => bail!("Invalid memory trim level {:?}", level),
- };
- let command = BalloonControlCommand::Adjust {
- num_bytes: total_memory * pct / 100,
- wait_for_success: false,
- };
- if let Err(e) = vm_control::client::handle_request(
- &VmRequest::BalloonCommand(command),
- &self.crosvm_control_socket_path,
- ) {
- bail!("Error sending balloon adjustment: {:?}", e);
+ let result =
+ match vm_control::client::handle_request(&request, &self.crosvm_control_socket_path) {
+ Ok(VmResponse::BalloonStats { stats: _, balloon_actual }) => balloon_actual,
+ Ok(VmResponse::Err(e)) => {
+ // ENOTSUP is returned when the balloon protocol is not initialized. This
+ // can occur for numerous reasons: Guest is still booting, guest doesn't
+ // support ballooning, host doesn't support ballooning. We don't log or
+ // raise an error in this case: trim is just a hint and we can ignore it.
+ if e.errno() != libc::ENOTSUP {
+ bail!("Errno return when requesting balloon stats: {}", e.errno())
}
+ 0
}
- }
- Ok(VmResponse::Err(e)) => {
- // ENOTSUP is returned when the balloon protocol is not initialized. This
- // can occur for numerous reasons: Guest is still booting, guest doesn't
- // support ballooning, host doesn't support ballooning. We don't log or
- // raise an error in this case: trim is just a hint and we can ignore it.
- if e.errno() != libc::ENOTSUP {
- bail!("Errno return when requesting balloon stats: {}", e.errno())
- }
- }
- e => bail!("Error requesting balloon stats: {:?}", e),
+ e => bail!("Error requesting balloon stats: {:?}", e),
+ };
+ Ok(result)
+ }
+
+ /// Responds to memory-trimming notifications by inflating the virtio
+ /// balloon to reclaim guest memory.
+ pub fn set_memory_balloon(&self, num_bytes: u64) -> Result<(), Error> {
+ let command = BalloonControlCommand::Adjust { num_bytes, wait_for_success: false };
+ if let Err(e) = vm_control::client::handle_request(
+ &VmRequest::BalloonCommand(command),
+ &self.crosvm_control_socket_path,
+ ) {
+ bail!("Error sending balloon adjustment: {:?}", e);
}
Ok(())
}
@@ -942,11 +934,8 @@
let swiotlb_size_mib = 2 * virtio_pci_device_count as u32;
command.arg("--swiotlb").arg(swiotlb_size_mib.to_string());
- // b/346770542 for consistent "usable" memory across protected and non-protected VMs under
- // pKVM.
- if hypervisor_props::is_pkvm()? {
- memory_mib = memory_mib.map(|m| m.saturating_add(swiotlb_size_mib));
- }
+ // b/346770542 for consistent "usable" memory across protected and non-protected VMs.
+ memory_mib = memory_mib.map(|m| m.saturating_add(swiotlb_size_mib));
// Workaround to keep crash_dump from trying to read protected guest memory.
// Context in b/238324526.
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl
index 9d1d5d5..afa25e2 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualMachine.aidl
@@ -16,7 +16,6 @@
package android.system.virtualizationservice;
import android.system.virtualizationservice.IVirtualMachineCallback;
-import android.system.virtualizationservice.MemoryTrimLevel;
import android.system.virtualizationservice.VirtualMachineState;
interface IVirtualMachine {
@@ -42,8 +41,9 @@
*/
void stop();
- /** Communicate app low-memory notifications to the VM. */
- void onTrimMemory(MemoryTrimLevel level);
+ /** Access to the VM's memory balloon. */
+ long getMemoryBalloon();
+ void setMemoryBalloon(long num_bytes);
/** Open a vsock connection to the CID of the VM on the given port. */
ParcelFileDescriptor connectVsock(int port);
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/MemoryTrimLevel.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/MemoryTrimLevel.aidl
deleted file mode 100644
index 9ed9e99..0000000
--- a/virtualizationservice/aidl/android/system/virtualizationservice/MemoryTrimLevel.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2022 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 android.system.virtualizationservice;
-
-/**
- * Memory trim levels propagated from the app to the VM.
- */
-@Backing(type="int")
-enum MemoryTrimLevel {
- /* Same meaning as in ComponentCallbacks2 */
- TRIM_MEMORY_RUNNING_CRITICAL = 0,
- TRIM_MEMORY_RUNNING_LOW = 1,
- TRIM_MEMORY_RUNNING_MODERATE = 2,
-}
diff --git a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
index 7a69c07..c2b1fa8 100644
--- a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
+++ b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
@@ -83,7 +83,7 @@
private static final boolean DEBUG = true;
private ExecutorService mExecutorService;
private VirtualMachine mVirtualMachine;
- private ParcelFileDescriptor mCursorStream;
+ private CursorHandler mCursorHandler;
private ClipboardManager mClipboardManager;
private static final int RECORD_AUDIO_PERMISSION_REQUEST_CODE = 101;
@@ -414,9 +414,11 @@
try {
ParcelFileDescriptor[] pfds =
ParcelFileDescriptor.createSocketPair();
- mExecutorService.execute(
- new CursorHandler(cursorSurfaceView, pfds[0]));
- mCursorStream = pfds[0];
+ if (mCursorHandler != null) {
+ mCursorHandler.interrupt();
+ }
+ mCursorHandler = new CursorHandler(cursorSurfaceView, pfds[0]);
+ mCursorHandler.start();
runWithDisplayService(
(service) -> service.setCursorStream(pfds[1]));
} catch (Exception e) {
@@ -646,7 +648,7 @@
}
}
- static class CursorHandler implements Runnable {
+ static class CursorHandler extends Thread {
private final SurfaceView mSurfaceView;
private final ParcelFileDescriptor mStream;
@@ -662,6 +664,10 @@
ByteBuffer byteBuffer = ByteBuffer.allocate(8 /* (x: u32, y: u32) */);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
while (true) {
+ if (Thread.interrupted()) {
+ Log.d(TAG, "interrupted: exiting CursorHandler");
+ return;
+ }
byteBuffer.clear();
int bytes =
IoBridge.read(
@@ -669,6 +675,10 @@
byteBuffer.array(),
0,
byteBuffer.array().length);
+ if (bytes == -1) {
+ Log.e(TAG, "cannot read from cursor stream, stop the handler");
+ return;
+ }
float x = (float) (byteBuffer.getInt() & 0xFFFFFFFF);
float y = (float) (byteBuffer.getInt() & 0xFFFFFFFF);
mSurfaceView.post(