Android Platform
Android extends JVM support with SharedMemory for zero-copy IPC.
Implementation
| Zone | Android Type |
|---|---|
Heap | HeapByteBuffer |
Direct | DirectByteBuffer |
SharedMemory | SharedMemory (API 27+) or ParcelFileDescriptor pipes |
Parcelable Support
All JvmBuffer instances are Parcelable:
// In your Service
val buffer = PlatformBuffer.allocate(1024, AllocationZone.SharedMemory)
buffer.writeBytes(imageData)
buffer.resetForRead()
// Send via Binder
val intent = Intent(context, MyService::class.java)
intent.putExtra("buffer", buffer as Parcelable)
startService(intent)
// Receive in Service
val buffer = intent.getParcelableExtra<PlatformBuffer>("buffer")
val data = buffer?.readByteArray(buffer.remaining())
SharedMemory (API 27+)
Zero-copy IPC using Android's SharedMemory:
// Create shared buffer
val buffer = PlatformBuffer.allocate(
size = 1024 * 1024, // 1MB
zone = AllocationZone.SharedMemory
)
// Write data
buffer.writeBytes(largeData)
buffer.resetForRead()
// Pass through Binder - no copy!
parcel.writeParcelable(buffer as Parcelable, 0)
Pre-API 27 Fallback
On older devices, uses ParcelFileDescriptor pipes:
// Same API, but data is piped through file descriptors
val buffer = PlatformBuffer.allocate(1024, AllocationZone.SharedMemory)
// Works on all Android versions, but with copy overhead on old devices
Memory Considerations
Direct Buffers
// Large buffers should use Direct to avoid GC
val videoFrame = PlatformBuffer.allocate(
size = 1920 * 1080 * 4, // 8MB RGBA
zone = AllocationZone.Direct
)
Buffer Pooling for Camera/Video
class CameraProcessor {
private val pool = BufferPool(
threadingMode = ThreadingMode.MultiThreaded,
maxPoolSize = 8, // Match camera buffer count
defaultBufferSize = 1920 * 1080 * 4,
allocationZone = AllocationZone.Direct
)
fun onFrameAvailable(frame: ByteArray) {
pool.withBuffer(frame.size) { buffer ->
buffer.writeBytes(frame)
buffer.resetForRead()
processFrame(buffer)
}
}
}
ContentProvider Integration
class DataProvider : ContentProvider() {
override fun call(method: String, arg: String?, extras: Bundle?): Bundle {
val buffer = extras?.getParcelable<PlatformBuffer>("data")
// Process buffer...
val result = Bundle()
result.putParcelable("result", responseBuffer as Parcelable)
return result
}
}
Best Practices
- Use SharedMemory for IPC - zero-copy between processes
- Pool camera buffers - avoid allocation during capture
- Direct for large media - video frames, images
- Watch memory limits - Android kills background apps aggressively