1 // Copyright 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "GoldfishAddressSpaceStream.h"
16 
17 #include "goldfish_address_space.h"
18 
createGoldfishAddressSpaceStream(size_t ignored_bufSize,HealthMonitor<> * healthMonitor)19 AddressSpaceStream* createGoldfishAddressSpaceStream(size_t ignored_bufSize,
20                                                      HealthMonitor<>* healthMonitor) {
21     // Ignore incoming ignored_bufSize
22     (void)ignored_bufSize;
23 
24     auto handle = goldfish_address_space_open();
25     address_space_handle_t child_device_handle;
26 
27     if (!goldfish_address_space_set_subdevice_type(handle, GoldfishAddressSpaceSubdeviceType::Graphics, &child_device_handle)) {
28         ALOGE("AddressSpaceStream::create failed (initial device create)\n");
29         goldfish_address_space_close(handle);
30         return nullptr;
31     }
32 
33     struct address_space_ping request;
34     request.metadata = ASG_GET_RING;
35     if (!goldfish_address_space_ping(child_device_handle, &request)) {
36         ALOGE("AddressSpaceStream::create failed (get ring)\n");
37         goldfish_address_space_close(child_device_handle);
38         return nullptr;
39     }
40 
41     uint64_t ringOffset = request.metadata;
42 
43     request.metadata = ASG_GET_BUFFER;
44     if (!goldfish_address_space_ping(child_device_handle, &request)) {
45         ALOGE("AddressSpaceStream::create failed (get buffer)\n");
46         goldfish_address_space_close(child_device_handle);
47         return nullptr;
48     }
49 
50     uint64_t bufferOffset = request.metadata;
51     uint64_t bufferSize = request.size;
52 
53     if (!goldfish_address_space_claim_shared(
54         child_device_handle, ringOffset, sizeof(asg_ring_storage))) {
55         ALOGE("AddressSpaceStream::create failed (claim ring storage)\n");
56         goldfish_address_space_close(child_device_handle);
57         return nullptr;
58     }
59 
60     if (!goldfish_address_space_claim_shared(
61         child_device_handle, bufferOffset, bufferSize)) {
62         ALOGE("AddressSpaceStream::create failed (claim buffer storage)\n");
63         goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
64         goldfish_address_space_close(child_device_handle);
65         return nullptr;
66     }
67 
68     char* ringPtr = (char*)goldfish_address_space_map(
69         child_device_handle, ringOffset, sizeof(struct asg_ring_storage));
70 
71     if (!ringPtr) {
72         ALOGE("AddressSpaceStream::create failed (map ring storage)\n");
73         goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
74         goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
75         goldfish_address_space_close(child_device_handle);
76         return nullptr;
77     }
78 
79     char* bufferPtr = (char*)goldfish_address_space_map(
80         child_device_handle, bufferOffset, bufferSize);
81 
82     if (!bufferPtr) {
83         ALOGE("AddressSpaceStream::create failed (map buffer storage)\n");
84         goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage));
85         goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
86         goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
87         goldfish_address_space_close(child_device_handle);
88         return nullptr;
89     }
90 
91     struct asg_context context =
92         asg_context_create(
93             ringPtr, bufferPtr, bufferSize);
94 
95     request.metadata = ASG_SET_VERSION;
96     request.size = 1; // version 1
97 
98     if (!goldfish_address_space_ping(child_device_handle, &request)) {
99         ALOGE("AddressSpaceStream::create failed (get buffer)\n");
100         goldfish_address_space_unmap(bufferPtr, bufferSize);
101         goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage));
102         goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
103         goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
104         goldfish_address_space_close(child_device_handle);
105         return nullptr;
106     }
107 
108     uint32_t version = request.size;
109 
110     context.ring_config->transfer_mode = 1;
111     context.ring_config->host_consumed_pos = 0;
112     context.ring_config->guest_write_pos = 0;
113 
114     struct address_space_ops ops = {
115         .open = goldfish_address_space_open,
116         .close = goldfish_address_space_close,
117         .claim_shared = goldfish_address_space_claim_shared,
118         .unclaim_shared = goldfish_address_space_unclaim_shared,
119         .map = goldfish_address_space_map,
120         .unmap = goldfish_address_space_unmap,
121         .set_subdevice_type = goldfish_address_space_set_subdevice_type,
122         .ping = goldfish_address_space_ping,
123     };
124 
125     AddressSpaceStream* res =
126         new AddressSpaceStream(
127             child_device_handle, version, context,
128             ringOffset, bufferOffset, ops, healthMonitor);
129 
130     return res;
131 }