// 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. #include "GoldfishAddressSpaceStream.h" #include "goldfish_address_space.h" AddressSpaceStream* createGoldfishAddressSpaceStream(size_t ignored_bufSize, HealthMonitor<>* healthMonitor) { // Ignore incoming ignored_bufSize (void)ignored_bufSize; auto handle = goldfish_address_space_open(); address_space_handle_t child_device_handle; if (!goldfish_address_space_set_subdevice_type(handle, GoldfishAddressSpaceSubdeviceType::Graphics, &child_device_handle)) { ALOGE("AddressSpaceStream::create failed (initial device create)\n"); goldfish_address_space_close(handle); return nullptr; } struct address_space_ping request; request.metadata = ASG_GET_RING; if (!goldfish_address_space_ping(child_device_handle, &request)) { ALOGE("AddressSpaceStream::create failed (get ring)\n"); goldfish_address_space_close(child_device_handle); return nullptr; } uint64_t ringOffset = request.metadata; request.metadata = ASG_GET_BUFFER; if (!goldfish_address_space_ping(child_device_handle, &request)) { ALOGE("AddressSpaceStream::create failed (get buffer)\n"); goldfish_address_space_close(child_device_handle); return nullptr; } uint64_t bufferOffset = request.metadata; uint64_t bufferSize = request.size; if (!goldfish_address_space_claim_shared( child_device_handle, ringOffset, sizeof(asg_ring_storage))) { ALOGE("AddressSpaceStream::create failed (claim ring storage)\n"); goldfish_address_space_close(child_device_handle); return nullptr; } if (!goldfish_address_space_claim_shared( child_device_handle, bufferOffset, bufferSize)) { ALOGE("AddressSpaceStream::create failed (claim buffer storage)\n"); goldfish_address_space_unclaim_shared(child_device_handle, ringOffset); goldfish_address_space_close(child_device_handle); return nullptr; } char* ringPtr = (char*)goldfish_address_space_map( child_device_handle, ringOffset, sizeof(struct asg_ring_storage)); if (!ringPtr) { ALOGE("AddressSpaceStream::create failed (map ring storage)\n"); goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset); goldfish_address_space_unclaim_shared(child_device_handle, ringOffset); goldfish_address_space_close(child_device_handle); return nullptr; } char* bufferPtr = (char*)goldfish_address_space_map( child_device_handle, bufferOffset, bufferSize); if (!bufferPtr) { ALOGE("AddressSpaceStream::create failed (map buffer storage)\n"); goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage)); goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset); goldfish_address_space_unclaim_shared(child_device_handle, ringOffset); goldfish_address_space_close(child_device_handle); return nullptr; } struct asg_context context = asg_context_create( ringPtr, bufferPtr, bufferSize); request.metadata = ASG_SET_VERSION; request.size = 1; // version 1 if (!goldfish_address_space_ping(child_device_handle, &request)) { ALOGE("AddressSpaceStream::create failed (get buffer)\n"); goldfish_address_space_unmap(bufferPtr, bufferSize); goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage)); goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset); goldfish_address_space_unclaim_shared(child_device_handle, ringOffset); goldfish_address_space_close(child_device_handle); return nullptr; } uint32_t version = request.size; context.ring_config->transfer_mode = 1; context.ring_config->host_consumed_pos = 0; context.ring_config->guest_write_pos = 0; struct address_space_ops ops = { .open = goldfish_address_space_open, .close = goldfish_address_space_close, .claim_shared = goldfish_address_space_claim_shared, .unclaim_shared = goldfish_address_space_unclaim_shared, .map = goldfish_address_space_map, .unmap = goldfish_address_space_unmap, .set_subdevice_type = goldfish_address_space_set_subdevice_type, .ping = goldfish_address_space_ping, }; AddressSpaceStream* res = new AddressSpaceStream( child_device_handle, version, context, ringOffset, bufferOffset, ops, healthMonitor); return res; }