1 // Copyright 2019 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 #include "host-common/address_space_device.h"
15 #include "host-common/AddressSpaceService.h"
16 #include "host-common/address_space_graphics.h"
17 #ifndef AEMU_MIN
18 #include "host-common/address_space_host_media.h"
19 #endif
20 #include "host-common/address_space_host_memory_allocator.h"
21 #include "host-common/address_space_shared_slots_host_memory_allocator.h"
22 #include "host-common/vm_operations.h"
23
24 #include "aemu/base/synchronization/Lock.h"
25
26 #include <map>
27 #include <unordered_map>
28 #include <memory>
29
30 using android::base::AutoLock;
31 using android::base::Lock;
32 using android::base::Stream;
33 using android::emulation::asg::AddressSpaceGraphicsContext;
34
35 using namespace android::emulation;
36
37 #define AS_DEVICE_DEBUG 0
38
39 #if AS_DEVICE_DEBUG
40 #define AS_DEVICE_DPRINT(fmt,...) fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
41 #else
42 #define AS_DEVICE_DPRINT(fmt,...)
43 #endif
44
45 const QAndroidVmOperations* sVmOps = nullptr;
46
47 namespace {
48
49 class AddressSpaceDeviceState {
50 public:
51 AddressSpaceDeviceState() = default;
52 ~AddressSpaceDeviceState() = default;
53
genHandle()54 uint32_t genHandle() {
55 AutoLock lock(mContextsLock);
56
57 auto res = mHandleIndex;
58
59 if (!res) {
60 ++res;
61 mHandleIndex += 2;
62 } else {
63 ++mHandleIndex;
64 }
65
66 AS_DEVICE_DPRINT("new handle: %u", res);
67 return res;
68 }
69
destroyHandle(uint32_t handle)70 void destroyHandle(uint32_t handle) {
71 AS_DEVICE_DPRINT("erase handle: %u", handle);
72
73 std::unique_ptr<AddressSpaceDeviceContext> context;
74
75 {
76 AutoLock lock(mContextsLock);
77
78 auto contextDescriptionIt = mContexts.find(handle);
79 if (contextDescriptionIt == mContexts.end()) return;
80 auto& contextDescription = contextDescriptionIt->second;
81
82 context = std::move(contextDescription.device_context);
83
84 mContexts.erase(contextDescriptionIt);
85 }
86
87 // Destroy `context` without holding the lock.
88 }
89
tellPingInfo(uint32_t handle,uint64_t gpa)90 void tellPingInfo(uint32_t handle, uint64_t gpa) {
91 AutoLock lock(mContextsLock);
92 auto& contextDesc = mContexts[handle];
93 contextDesc.pingInfo =
94 (AddressSpaceDevicePingInfo*)
95 sVmOps->physicalMemoryGetAddr(gpa);
96 contextDesc.pingInfoGpa = gpa;
97 AS_DEVICE_DPRINT("Ping info: gpa 0x%llx @ %p\n", (unsigned long long)gpa,
98 contextDesc.pingInfo);
99 }
100
createInstance(const struct AddressSpaceCreateInfo & create)101 void createInstance(const struct AddressSpaceCreateInfo& create) {
102 AutoLock lock(mContextsLock);
103 auto& contextDesc = mContexts[create.handle];
104 contextDesc.device_context = buildAddressSpaceDeviceContext(create);
105 }
106
ping(uint32_t handle)107 void ping(uint32_t handle) {
108 AutoLock lock(mContextsLock);
109 auto& contextDesc = mContexts[handle];
110 AddressSpaceDevicePingInfo* pingInfo = contextDesc.pingInfo;
111
112 const uint64_t phys_addr = pingInfo->phys_addr;
113
114 AS_DEVICE_DPRINT(
115 "handle %u data 0x%llx -> %p size %llu meta 0x%llx\n", handle,
116 (unsigned long long)phys_addr,
117 sVmOps->physicalMemoryGetAddr(phys_addr),
118 (unsigned long long)pingInfo->size, (unsigned long long)pingInfo->metadata);
119
120 AddressSpaceDeviceContext *device_context = contextDesc.device_context.get();
121 if (device_context) {
122 device_context->perform(pingInfo);
123 } else {
124 // The first ioctl establishes the device type
125 struct AddressSpaceCreateInfo create = {0};
126 create.type = static_cast<AddressSpaceDeviceType>(pingInfo->metadata);
127 create.physAddr = phys_addr;
128
129 contextDesc.device_context = buildAddressSpaceDeviceContext(create);
130 pingInfo->metadata = contextDesc.device_context ? 0 : -1;
131 }
132 }
133
pingAtHva(uint32_t handle,AddressSpaceDevicePingInfo * pingInfo)134 void pingAtHva(uint32_t handle, AddressSpaceDevicePingInfo* pingInfo) {
135 AutoLock lock(mContextsLock);
136 auto& contextDesc = mContexts[handle];
137
138 const uint64_t phys_addr = pingInfo->phys_addr;
139
140 AS_DEVICE_DPRINT(
141 "handle %u data 0x%llx -> %p size %llu meta 0x%llx\n", handle,
142 (unsigned long long)phys_addr,
143 sVmOps->physicalMemoryGetAddr(phys_addr),
144 (unsigned long long)pingInfo->size, (unsigned long long)pingInfo->metadata);
145
146 AddressSpaceDeviceContext *device_context = contextDesc.device_context.get();
147 if (device_context) {
148 device_context->perform(pingInfo);
149 } else {
150 struct AddressSpaceCreateInfo create = {0};
151 create.type = static_cast<AddressSpaceDeviceType>(pingInfo->metadata);
152 create.physAddr = phys_addr;
153
154 contextDesc.device_context = buildAddressSpaceDeviceContext(create);
155 pingInfo->metadata = contextDesc.device_context ? 0 : -1;
156 }
157 }
158
registerDeallocationCallback(uint64_t gpa,void * context,address_space_device_deallocation_callback_t func)159 void registerDeallocationCallback(uint64_t gpa, void* context, address_space_device_deallocation_callback_t func) {
160 AutoLock lock(mContextsLock);
161 auto& currentCallbacks = mDeallocationCallbacks[gpa];
162
163 DeallocationCallbackEntry entry = {
164 context,
165 func,
166 };
167
168 currentCallbacks.push_back(entry);
169 }
170
runDeallocationCallbacks(uint64_t gpa)171 void runDeallocationCallbacks(uint64_t gpa) {
172 AutoLock lock(mContextsLock);
173
174 auto it = mDeallocationCallbacks.find(gpa);
175 if (it == mDeallocationCallbacks.end()) return;
176
177 auto& callbacks = it->second;
178
179 for (auto& entry: callbacks) {
180 entry.func(entry.context, gpa);
181 }
182
183 mDeallocationCallbacks.erase(gpa);
184 }
185
handleToContext(uint32_t handle)186 AddressSpaceDeviceContext* handleToContext(uint32_t handle) {
187 AutoLock lock(mContextsLock);
188 if (mContexts.find(handle) == mContexts.end()) return nullptr;
189
190 auto& contextDesc = mContexts[handle];
191 return contextDesc.device_context.get();
192 }
193
hostmemRegister(const struct MemEntry * entry)194 uint64_t hostmemRegister(const struct MemEntry *entry) {
195 return sVmOps->hostmemRegister(entry);
196 }
197
hostmemUnregister(uint64_t id)198 void hostmemUnregister(uint64_t id) {
199 sVmOps->hostmemUnregister(id);
200 }
201
save(Stream * stream) const202 void save(Stream* stream) const {
203 // Pre-save
204 for (const auto &kv : mContexts) {
205 const AddressSpaceContextDescription &desc = kv.second;
206 const AddressSpaceDeviceContext *device_context = desc.device_context.get();
207 if (device_context) {
208 device_context->preSave();
209 }
210 }
211
212 AddressSpaceGraphicsContext::globalStatePreSave();
213
214 // Save
215 AddressSpaceSharedSlotsHostMemoryAllocatorContext::globalStateSave(stream);
216 AddressSpaceGraphicsContext::globalStateSave(stream);
217
218 stream->putBe32(mHandleIndex);
219 stream->putBe32(mContexts.size());
220
221 for (const auto &kv : mContexts) {
222 const uint32_t handle = kv.first;
223 const AddressSpaceContextDescription &desc = kv.second;
224 const AddressSpaceDeviceContext *device_context = desc.device_context.get();
225
226 stream->putBe32(handle);
227 stream->putBe64(desc.pingInfoGpa);
228
229 if (device_context) {
230 stream->putByte(1);
231 stream->putBe32(device_context->getDeviceType());
232 device_context->save(stream);
233 } else {
234 stream->putByte(0);
235 }
236 }
237
238 // Post save
239
240 AddressSpaceGraphicsContext::globalStatePostSave();
241
242 for (const auto &kv : mContexts) {
243 const AddressSpaceContextDescription &desc = kv.second;
244 const AddressSpaceDeviceContext *device_context = desc.device_context.get();
245 if (device_context) {
246 device_context->postSave();
247 }
248 }
249 }
250
setLoadResources(AddressSpaceDeviceLoadResources resources)251 void setLoadResources(AddressSpaceDeviceLoadResources resources) {
252 mLoadResources = std::move(resources);
253 }
254
load(Stream * stream)255 bool load(Stream* stream) {
256 // First destroy all contexts, because
257 // this can be done while an emulator is running
258 clear();
259
260 if (!AddressSpaceSharedSlotsHostMemoryAllocatorContext::globalStateLoad(
261 stream,
262 get_address_space_device_control_ops(),
263 get_address_space_device_hw_funcs())) {
264 return false;
265 }
266
267 asg::AddressSpaceGraphicsContext::init(get_address_space_device_control_ops());
268
269 if (!AddressSpaceGraphicsContext::globalStateLoad(stream, mLoadResources)) {
270 return false;
271 }
272
273 const uint32_t handleIndex = stream->getBe32();
274 const size_t size = stream->getBe32();
275
276 Contexts contexts;
277 for (size_t i = 0; i < size; ++i) {
278 const uint32_t handle = stream->getBe32();
279 const uint64_t pingInfoGpa = stream->getBe64();
280
281 std::unique_ptr<AddressSpaceDeviceContext> context;
282 switch (stream->getByte()) {
283 case 0:
284 break;
285
286 case 1: {
287 struct AddressSpaceCreateInfo create = {0};
288 create.type = static_cast<AddressSpaceDeviceType>(stream->getBe32());
289 create.physAddr = pingInfoGpa;
290 create.fromSnapshot = true;
291
292 context = buildAddressSpaceDeviceContext(create);
293 if (!context || !context->load(stream)) {
294 return false;
295 }
296 }
297 break;
298
299 default:
300 return false;
301 }
302
303 auto &desc = contexts[handle];
304 desc.pingInfoGpa = pingInfoGpa;
305 if (desc.pingInfoGpa == ~0ULL) {
306 fprintf(stderr, "%s: warning: restoring hva-only ping\n", __func__);
307 } else {
308 desc.pingInfo = (AddressSpaceDevicePingInfo*)
309 sVmOps->physicalMemoryGetAddr(pingInfoGpa);
310 }
311 desc.device_context = std::move(context);
312 }
313
314 {
315 AutoLock lock(mContextsLock);
316 mHandleIndex = handleIndex;
317 mContexts = std::move(contexts);
318 }
319
320 return true;
321 }
322
clear()323 void clear() {
324 AutoLock lock(mContextsLock);
325 mContexts.clear();
326 AddressSpaceSharedSlotsHostMemoryAllocatorContext::globalStateClear();
327 auto it = mMemoryMappings.begin();
328 std::vector<std::pair<uint64_t, uint64_t>> gpasSizesToErase;
329 for (auto it: mMemoryMappings) {
330 auto gpa = it.first;
331 auto size = it.second.second;
332 gpasSizesToErase.push_back({gpa, size});
333 }
334 for (const auto& gpaSize : gpasSizesToErase) {
335 removeMemoryMappingLocked(gpaSize.first, gpaSize.second);
336 }
337 mMemoryMappings.clear();
338 }
339
addMemoryMapping(uint64_t gpa,void * ptr,uint64_t size)340 bool addMemoryMapping(uint64_t gpa, void *ptr, uint64_t size) {
341 AutoLock lock(mMemoryMappingsLock);
342 return addMemoryMappingLocked(gpa, ptr, size);
343 }
344
removeMemoryMapping(uint64_t gpa,uint64_t size)345 bool removeMemoryMapping(uint64_t gpa, uint64_t size) {
346 AutoLock lock(mMemoryMappingsLock);
347 return removeMemoryMappingLocked(gpa, size);
348 }
349
getHostPtr(uint64_t gpa) const350 void *getHostPtr(uint64_t gpa) const {
351 AutoLock lock(mMemoryMappingsLock);
352 return getHostPtrLocked(gpa);
353 }
354
355 private:
356 mutable Lock mContextsLock;
357 uint32_t mHandleIndex = 1;
358 typedef std::unordered_map<uint32_t, AddressSpaceContextDescription> Contexts;
359 Contexts mContexts;
360
buildAddressSpaceDeviceContext(const struct AddressSpaceCreateInfo & create)361 std::unique_ptr<AddressSpaceDeviceContext> buildAddressSpaceDeviceContext(
362 const struct AddressSpaceCreateInfo& create) {
363 typedef std::unique_ptr<AddressSpaceDeviceContext> DeviceContextPtr;
364
365 switch (create.type) {
366 case AddressSpaceDeviceType::Graphics:
367 asg::AddressSpaceGraphicsContext::init(get_address_space_device_control_ops());
368 return DeviceContextPtr(new asg::AddressSpaceGraphicsContext(create));
369 #ifndef AEMU_MIN
370 case AddressSpaceDeviceType::Media:
371 AS_DEVICE_DPRINT("allocating media context");
372 return DeviceContextPtr(
373 new AddressSpaceHostMediaContext(create, get_address_space_device_control_ops()));
374 #endif
375 case AddressSpaceDeviceType::Sensors:
376 return nullptr;
377 case AddressSpaceDeviceType::Power:
378 return nullptr;
379 case AddressSpaceDeviceType::GenericPipe:
380 return nullptr;
381 case AddressSpaceDeviceType::HostMemoryAllocator:
382 return DeviceContextPtr(new AddressSpaceHostMemoryAllocatorContext(
383 get_address_space_device_control_ops(),
384 get_address_space_device_hw_funcs()));
385 case AddressSpaceDeviceType::SharedSlotsHostMemoryAllocator:
386 return DeviceContextPtr(new AddressSpaceSharedSlotsHostMemoryAllocatorContext(
387 get_address_space_device_control_ops(),
388 get_address_space_device_hw_funcs()));
389
390 case AddressSpaceDeviceType::VirtioGpuGraphics:
391 asg::AddressSpaceGraphicsContext::init(get_address_space_device_control_ops());
392 return DeviceContextPtr(new asg::AddressSpaceGraphicsContext(create));
393
394 default:
395 AS_DEVICE_DPRINT("Bad device type");
396 return nullptr;
397 }
398 }
399
addMemoryMappingLocked(uint64_t gpa,void * ptr,uint64_t size)400 bool addMemoryMappingLocked(uint64_t gpa, void *ptr, uint64_t size) {
401 if (mMemoryMappings.insert({gpa, {ptr, size}}).second) {
402 sVmOps->mapUserBackedRam(gpa, ptr, size);
403 return true;
404 } else {
405 fprintf(stderr, "%s: failed: hva %p -> gpa [0x%llx 0x%llx]\n", __func__,
406 ptr,
407 (unsigned long long)gpa,
408 (unsigned long long)size);
409 return false;
410 }
411 }
412
removeMemoryMappingLocked(uint64_t gpa,uint64_t size)413 bool removeMemoryMappingLocked(uint64_t gpa, uint64_t size) {
414 if (mMemoryMappings.erase(gpa) > 0) {
415 sVmOps->unmapUserBackedRam(gpa, size);
416 return true;
417 } else {
418 fprintf(stderr, "%s: failed: gpa [0x%llx 0x%llx]\n", __func__,
419 (unsigned long long)gpa,
420 (unsigned long long)size);
421 *(uint32_t*)(123) = 12;
422 return false;
423 }
424 }
425
getHostPtrLocked(uint64_t gpa) const426 void *getHostPtrLocked(uint64_t gpa) const {
427 auto i = mMemoryMappings.lower_bound(gpa); // i->first >= gpa (or i==end)
428 if ((i != mMemoryMappings.end()) && (i->first == gpa)) {
429 return i->second.first; // gpa is exactly the beginning of the range
430 } else if (i == mMemoryMappings.begin()) {
431 return nullptr; // can't '--i', see below
432 } else {
433 --i;
434
435 if ((i->first + i->second.second) > gpa) {
436 // move the host ptr by +(gpa-base)
437 return static_cast<char *>(i->second.first) + (gpa - i->first);
438 } else {
439 return nullptr; // the range does not cover gpa
440 }
441 }
442 }
443
444 mutable Lock mMemoryMappingsLock;
445 std::map<uint64_t, std::pair<void *, uint64_t>> mMemoryMappings; // do not save/load
446
447 struct DeallocationCallbackEntry {
448 void* context;
449 address_space_device_deallocation_callback_t func;
450 };
451
452 std::map<uint64_t, std::vector<DeallocationCallbackEntry>> mDeallocationCallbacks; // do not save/load, users re-register on load
453
454 // Not saved/loaded. Externally owned resources used during load.
455 std::optional<AddressSpaceDeviceLoadResources> mLoadResources;
456 };
457
sAddressSpaceDeviceState()458 static AddressSpaceDeviceState* sAddressSpaceDeviceState() {
459 static AddressSpaceDeviceState* s = new AddressSpaceDeviceState;
460 return s;
461 }
462
sAddressSpaceDeviceGenHandle()463 static uint32_t sAddressSpaceDeviceGenHandle() {
464 return sAddressSpaceDeviceState()->genHandle();
465 }
466
sAddressSpaceDeviceDestroyHandle(uint32_t handle)467 static void sAddressSpaceDeviceDestroyHandle(uint32_t handle) {
468 sAddressSpaceDeviceState()->destroyHandle(handle);
469 }
470
sAddressSpaceDeviceCreateInstance(const struct AddressSpaceCreateInfo & create)471 static void sAddressSpaceDeviceCreateInstance(const struct AddressSpaceCreateInfo& create) {
472 sAddressSpaceDeviceState()->createInstance(create);
473 }
474
sAddressSpaceDeviceTellPingInfo(uint32_t handle,uint64_t gpa)475 static void sAddressSpaceDeviceTellPingInfo(uint32_t handle, uint64_t gpa) {
476 sAddressSpaceDeviceState()->tellPingInfo(handle, gpa);
477 }
478
sAddressSpaceDevicePing(uint32_t handle)479 static void sAddressSpaceDevicePing(uint32_t handle) {
480 sAddressSpaceDeviceState()->ping(handle);
481 }
482
sAddressSpaceDeviceAddMemoryMapping(uint64_t gpa,void * ptr,uint64_t size)483 int sAddressSpaceDeviceAddMemoryMapping(uint64_t gpa, void *ptr, uint64_t size) {
484 return sAddressSpaceDeviceState()->addMemoryMapping(gpa, ptr, size) ? 1 : 0;
485 }
486
sAddressSpaceDeviceRemoveMemoryMapping(uint64_t gpa,void * ptr,uint64_t size)487 int sAddressSpaceDeviceRemoveMemoryMapping(uint64_t gpa, void *ptr, uint64_t size) {
488 (void)ptr; // TODO(lfy): remove arg
489 return sAddressSpaceDeviceState()->removeMemoryMapping(gpa, size) ? 1 : 0;
490 }
491
sAddressSpaceDeviceGetHostPtr(uint64_t gpa)492 void* sAddressSpaceDeviceGetHostPtr(uint64_t gpa) {
493 return sAddressSpaceDeviceState()->getHostPtr(gpa);
494 }
495
sAddressSpaceHandleToContext(uint32_t handle)496 static void* sAddressSpaceHandleToContext(uint32_t handle) {
497 return (void*)(sAddressSpaceDeviceState()->handleToContext(handle));
498 }
499
sAddressSpaceDeviceClear()500 static void sAddressSpaceDeviceClear() {
501 sAddressSpaceDeviceState()->clear();
502 }
503
sAddressSpaceDeviceHostmemRegister(const struct MemEntry * entry)504 static uint64_t sAddressSpaceDeviceHostmemRegister(const struct MemEntry *entry) {
505 return sAddressSpaceDeviceState()->hostmemRegister(entry);
506 }
507
sAddressSpaceDeviceHostmemUnregister(uint64_t id)508 static void sAddressSpaceDeviceHostmemUnregister(uint64_t id) {
509 sAddressSpaceDeviceState()->hostmemUnregister(id);
510 }
511
sAddressSpaceDevicePingAtHva(uint32_t handle,void * hva)512 static void sAddressSpaceDevicePingAtHva(uint32_t handle, void* hva) {
513 sAddressSpaceDeviceState()->pingAtHva(
514 handle, (AddressSpaceDevicePingInfo*)hva);
515 }
516
sAddressSpaceDeviceRegisterDeallocationCallback(void * context,uint64_t gpa,address_space_device_deallocation_callback_t func)517 static void sAddressSpaceDeviceRegisterDeallocationCallback(
518 void* context, uint64_t gpa, address_space_device_deallocation_callback_t func) {
519 sAddressSpaceDeviceState()->registerDeallocationCallback(gpa, context, func);
520 }
521
sAddressSpaceDeviceRunDeallocationCallbacks(uint64_t gpa)522 static void sAddressSpaceDeviceRunDeallocationCallbacks(uint64_t gpa) {
523 sAddressSpaceDeviceState()->runDeallocationCallbacks(gpa);
524 }
525
sAddressSpaceDeviceControlGetHwFuncs()526 static const struct AddressSpaceHwFuncs* sAddressSpaceDeviceControlGetHwFuncs() {
527 return get_address_space_device_hw_funcs();
528 }
529
530
531 } // namespace
532
533 extern "C" {
534
535 static struct address_space_device_control_ops sAddressSpaceDeviceOps = {
536 &sAddressSpaceDeviceGenHandle, // gen_handle
537 &sAddressSpaceDeviceDestroyHandle, // destroy_handle
538 &sAddressSpaceDeviceTellPingInfo, // tell_ping_info
539 &sAddressSpaceDevicePing, // ping
540 &sAddressSpaceDeviceAddMemoryMapping, // add_memory_mapping
541 &sAddressSpaceDeviceRemoveMemoryMapping, // remove_memory_mapping
542 &sAddressSpaceDeviceGetHostPtr, // get_host_ptr
543 &sAddressSpaceHandleToContext, // handle_to_context
544 &sAddressSpaceDeviceClear, // clear
545 &sAddressSpaceDeviceHostmemRegister, // hostmem register
546 &sAddressSpaceDeviceHostmemUnregister, // hostmem unregister
547 &sAddressSpaceDevicePingAtHva, // ping_at_hva
548 &sAddressSpaceDeviceRegisterDeallocationCallback, // register_deallocation_callback
549 &sAddressSpaceDeviceRunDeallocationCallbacks, // run_deallocation_callbacks
550 &sAddressSpaceDeviceControlGetHwFuncs, // control_get_hw_funcs
551 &sAddressSpaceDeviceCreateInstance, // create_instance
552 };
553
get_address_space_device_control_ops(void)554 struct address_space_device_control_ops* get_address_space_device_control_ops(void) {
555 return &sAddressSpaceDeviceOps;
556 }
557
558 static const struct AddressSpaceHwFuncs* sAddressSpaceHwFuncs = nullptr;
559
address_space_set_hw_funcs(const AddressSpaceHwFuncs * hwFuncs)560 const struct AddressSpaceHwFuncs* address_space_set_hw_funcs(
561 const AddressSpaceHwFuncs* hwFuncs) {
562 const AddressSpaceHwFuncs* result = sAddressSpaceHwFuncs;
563 sAddressSpaceHwFuncs = hwFuncs;
564 return result;
565 }
566
get_address_space_device_hw_funcs(void)567 const struct AddressSpaceHwFuncs* get_address_space_device_hw_funcs(void) {
568 return sAddressSpaceHwFuncs;
569 }
570
address_space_set_vm_operations(const QAndroidVmOperations * vmops)571 void address_space_set_vm_operations(const QAndroidVmOperations* vmops) {
572 sVmOps = vmops;
573 }
574
575 } // extern "C"
576
577 namespace android {
578 namespace emulation {
579
goldfish_address_space_set_vm_operations(const QAndroidVmOperations * vmops)580 void goldfish_address_space_set_vm_operations(const QAndroidVmOperations* vmops) {
581 sVmOps = vmops;
582 }
583
goldfish_address_space_get_vm_operations()584 const QAndroidVmOperations* goldfish_address_space_get_vm_operations() {
585 return sVmOps;
586 }
587
goldfish_address_space_memory_state_set_load_resources(AddressSpaceDeviceLoadResources resources)588 int goldfish_address_space_memory_state_set_load_resources(
589 AddressSpaceDeviceLoadResources resources) {
590 sAddressSpaceDeviceState()->setLoadResources(std::move(resources));
591 return 0;
592 }
593
goldfish_address_space_memory_state_load(android::base::Stream * stream)594 int goldfish_address_space_memory_state_load(android::base::Stream *stream) {
595 return sAddressSpaceDeviceState()->load(stream) ? 0 : 1;
596 }
597
goldfish_address_space_memory_state_save(android::base::Stream * stream)598 int goldfish_address_space_memory_state_save(android::base::Stream *stream) {
599 sAddressSpaceDeviceState()->save(stream);
600 return 0;
601 }
602
603 } // namespace emulation
604 } // namespace android
605