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