Parcel.writeStrongBinder will call flatten_binder. From code of flatten_binder, we know that when "IBinder *local = binder->localBinder();" is not NULL, memory address will be used to transfer Binder between different process.
status_t flatten_binder(const sp<ProcessState>& proc,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.handle = handle;
obj.cookie = NULL;
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = local->getWeakRefs();
obj.cookie = local;
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = NULL;
obj.cookie = NULL;
}
return finish_flatten_binder(binder, obj, out);
}
For binder server implementation, they are descendants of BBinder. BBinder return memory address of itself as localBinder()
BBinder* BBinder::localBinder()
{
return this;
}
So conclusion: memory address is used as binder handle. There is no mechanism of binder handle generation and maintenance logic.