Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[gbinder] Expose internal transaction codes, add binder error status codes. JB#61891 #125

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

abranson
Copy link
Contributor

@abranson abranson commented Apr 5, 2024

Useful for implementation of DUMP and other internal transactions (except for the silly ones). Also define proper error codes for them as the current GBINDER_STATUS_FAILED is not recognized.

typedef enum gbinder_status {
GBINDER_STATUS_OK = 0,
GBINDER_STATUS_FAILED,
GBINDER_STATUS_DEAD_OBJECT
GBINDER_STATUS_UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is supposed to be a stable interface, the externally exposed status codes must be a stable enum, and internal errors need to be translated internally from ENOSYS or whatever into the interface enum values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that makes sense, though it's more the other way around - we need to be able to return these codes like UNKNOWN_TRANSACTION and PERMISSION_DENIED in order to accurately flag errors in calls to binder services. Currently returning GBINDER_STATUS_FAILED in a GBinderLocalReply causes 'Unknown binder error code. 0x1' when interpreted here. So they're not always being caught right now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the value passed to gbinder_driver_reply_status() then what about replacing GBINDER_STATUS_FAILED with INT32_MIN and GBINDER_STATUS_DEAD_OBJECT with -EPIPE. Would that do it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly. We should be sure that the actual values will be completely internal, i.e. they're translated back when returned by Android services too.

Can we not add the others to the end of the enum without breaking anything though? We really need GBINDER_STATUS_PERMISSION_DENIED (-EPERM) to get these tests working nicely, but I can see GBINDER_STATUS_UNKNOWN_TRANSACTION (-EBADMSG) should be what everything returns in the default case of all transaction code switches. Really any of them can be returned by Android services.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are going to be completely internal, then they would have to be replaced in requests too. I guess gbinder_driver_txstatus would be the place to do that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a few additional public enum values feels like the way to go and gbinder_driver_txstatus() does seem to be the right place for the conversion, although I'm a bit puzzled by the switch under the "Filter out special cases" comment - it seems to do the conversion wrong way, e.g. replacing GBINDER_STATUS_DEAD_OBJECT with -EFAULT. Now that I'm looking at it, I'd say it should convert e.g. -EPIPE to GBINDER_STATUS_DEAD_OBJECT since that's what's going to be returned as a status by e.g. gbinder_client_transact() and friends (unless I'm missing something)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I'm glad I wasn't the only one confused by that. I had no idea where that EFAULT had come from. So my plan is to convert FAILED and DEAD_OBJECT in there and reply_status, and add the others with their actual values so that's not necessary. Is that ok, or would you rather they were all converted?


#define GBINDER_FIRST_CALL_TRANSACTION (0x00000001)
#define GBINDER_TRANSACTION(c2,c3,c4) GBINDER_FOURCC('_',c2,c3,c4)
#define GBINDER_PING_TRANSACTION GBINDER_TRANSACTION('P','N','G')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this doesn't break anything, I don't see much of a value in defining internal RPC protocol specific constants in public header files. One of the design goals has been to make the API as independent on the underlying implementation as possible and this looks like a step in the opposite direction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to implement DUMP to pass CTS tests, so we need to either paste this into other code or use it from here. The binder_dump test pastes it though, so is that what you would prefer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather have these transaction codes defined in places where they're being used. I generally don't like duplicating anything, but in this particular case I don't think it's worth the trouble. Adding HIDL_FOURCC macro is OK, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel dump is ok to have in the headers though? It's not really an internal transaction, more a service specific one. The others probably can be kept internal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could reduce this set to only the transactions that are the responsibility of the service to implement? This particular test we're dealing with (ServicePermissionsTest#testDumpProtected) requires that DUMP is implemented for every service, so it seems like a definition that really must be used or defined by every AIDL service.

I can understand keeping things like PING out of the public declaration, as that's completely handled internally and isn't something that services need to care about at all, if I have that right? But they've mixed up internal low-level operations with standard interface definitions here. From what I can see used in Android, most seem to be intended to be handled at a lower level except for maybe SHELL_COMMAND and SYSPROPS.

Maybe in HIDL they are all truly internal, so it's not necessary to make any of them public. I'll take that whole block out.

#define GBINDER_EXTENSION_TRANSACTION GBINDER_TRANSACTION('E','X','T'),
#define GBINDER_DEBUG_PID_TRANSACTION GBINDER_TRANSACTION('P','I','D'),
#define GBINDER_SET_RPC_CLIENT_TRANSACTION GBINDER_TRANSACTION('R','P','C'),
#undef GBINDER_FOURCC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GBINDER_FOURCC macro has been there since the very beginning, may be considered part of the compile-time API and should remain defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes sorry, I thought I was moving that over from the private headers. I think I should undef GBINDER_TRANSACTION here though instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If GBINDER_TRANSACTION and HIDL_FOURCC macros are to be defined in the public headers, I suggest to call them e.g. GBINDER_AIDL_TRANSACTION and GBINDER_HIDL_TRANSACTION to avoid compile-time collisions with other macros with HIDL_ prefix. And I still think that defining individual transaction codes would be an overkill.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. After a bit more digging yesterday I did see that the response to the INTERFACE call just should be interface descriptor string, but that's probably still too high level to handle in gbinder.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AIDL-style INTERFACE transactions are handled by gbinder_local_object_interface_transaction() and HIDL-style GET_DESCRIPTOR are handled by gbinder_local_object_hidl_get_descriptor_transaction(), are BTW that happens on the looper thread because the object's interface information is immutable and there's nothing to synchronize with the main thread. Are you saying that the response format for those transactions has changed?

@abranson abranson force-pushed the newtypes branch 2 times, most recently from 985b03c to 3d324a3 Compare April 9, 2024 09:43
@abranson
Copy link
Contributor Author

Any good now?

@monich
Copy link
Contributor

monich commented Apr 17, 2024

sorry, I haven't had time to really look at it past weekend, please give me a bit more time...

@abranson
Copy link
Contributor Author

No problem, we defined everything in other places for now so we're not blocked or anything.

break;
default:
mapped_status = status;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing break

txstatus = GBINDER_STATUS_UNKNOWN_ERROR;
break;
case GBINDER_STATUS_DEAD_OBJECT:
txstatus = (-EPIPE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another break is missing, and isn't this switch supposed to convert things like INT32_MIN, -EPIPE etc, into the interface values e.g. GBINDER_STATUS_DEAD_OBJECT?

…es. JB#61891

Useful for implementation of DUMP and other internal transactions (except
for the silly ones). Also define proper status codes and translate the
existing ones as the current GBINDER_STATUS_FAILED is not recognized.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants