-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Binder/AIDL content updates #1618
Changes from 21 commits
ca53547
fcddc17
f634395
8756902
0d132ef
c94e0f2
dc837fc
829a75c
3af6844
6b6f112
af905af
dd6365d
dde7958
1029f40
9cbe86f
d76d7f4
7eb9cb7
ea184a6
2b87d25
995005a
bc415a1
2f51ba2
f517a4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Birthday Service Tutorial | ||
|
||
To illustrate how to use Rust with Binder, we're going to walk through the | ||
process of creating a Binder interface. We're then going to both implement the | ||
described service and write client code that talks to that service. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.example.birthdayservice; | ||
|
||
parcelable BirthdayInfo { | ||
String name; | ||
int years; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// ANCHOR: IBirthdayInfoProvider | ||
package com.example.birthdayservice; | ||
|
||
interface IBirthdayInfoProvider { | ||
String name(); | ||
int years(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,11 +12,15 @@ | |
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// ANCHOR: IBirthdayService | ||
//! Implementation of the `IBirthdayService` AIDL interface. | ||
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayInfoProvider::{IBirthdayInfoProvider, BpBirthdayInfoProvider}; | ||
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService; | ||
use com_example_birthdayservice::binder; | ||
use com_example_birthdayservice::aidl::com::example::birthdayservice::BirthdayInfo::BirthdayInfo; | ||
use com_example_birthdayservice::binder::{self, ParcelFileDescriptor, SpIBinder, Strong}; | ||
use std::fs::File; | ||
use std::io::Read; | ||
|
||
// ANCHOR: IBirthdayService | ||
/// The `IBirthdayService` implementation. | ||
pub struct BirthdayService; | ||
|
||
|
@@ -26,4 +30,64 @@ impl IBirthdayService for BirthdayService { | |
fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result<String> { | ||
Ok(format!("Happy Birthday {name}, congratulations with the {years} years!")) | ||
} | ||
// ANCHOR_END: IBirthdayService | ||
|
||
fn wishWithInfo(&self, info: &BirthdayInfo) -> binder::Result<String> { | ||
Ok(format!( | ||
"Happy Birthday {}, congratulations with the {} years!", | ||
info.name, info.years, | ||
)) | ||
} | ||
|
||
fn wishWithProvider( | ||
&self, | ||
provider: &Strong<dyn IBirthdayInfoProvider>, | ||
) -> binder::Result<String> { | ||
Ok(format!( | ||
"Happy Birthday {}, congratulations with the {} years!", | ||
provider.name()?, | ||
provider.years()?, | ||
)) | ||
} | ||
|
||
fn wishWithErasedProvider( | ||
&self, | ||
provider: &SpIBinder, | ||
) -> binder::Result<String> { | ||
use binder::binder_impl::Proxy; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this re-exported by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does not currently appear to be re-exported. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Never mind, see the next comment. |
||
|
||
// Convert the `IBinder` to a concrete interface. | ||
let provider = BpBirthdayInfoProvider::from_binder(provider.clone())?; | ||
randomPoison marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Ok(format!( | ||
"Happy Birthday {}, congratulations with the {} years!", | ||
provider.name()?, | ||
provider.years()?, | ||
)) | ||
} | ||
|
||
// ANCHOR: wishFromFile | ||
fn wishFromFile( | ||
&self, | ||
info_file: &ParcelFileDescriptor, | ||
) -> binder::Result<String> { | ||
// Convert the file descriptor to a `File`. `ParcelFileDescriptor` wraps | ||
// an `OwnedFd`, which can be cloned and then used to create a `File` | ||
// object. | ||
let mut info_file = info_file | ||
.as_ref() | ||
.try_clone() | ||
randomPoison marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.map(File::from) | ||
.expect("Invalid file handle"); | ||
|
||
let mut contents = String::new(); | ||
info_file.read_to_string(&mut contents).unwrap(); | ||
|
||
let mut lines = contents.lines(); | ||
let name = lines.next().unwrap(); | ||
let years: i32 = lines.next().unwrap().parse().unwrap(); | ||
|
||
Ok(format!("Happy Birthday {name}, congratulations with the {years} years!")) | ||
} | ||
// ANCHOR_END: wishFromFile | ||
} |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Changing API | ||
|
||
Let us extend the API with more functionality: we want to let clients specify a | ||
list of lines for the birthday card: | ||
|
||
```java | ||
package com.example.birthdayservice; | ||
|
||
/** Birthday service interface. */ | ||
interface IBirthdayService { | ||
/** Generate a Happy Birthday message. */ | ||
String wishHappyBirthday(String name, int years, in String[] text); | ||
} | ||
``` | ||
|
||
This results in an updated trait definition for `IBirthdayService`: | ||
|
||
```rust,ignore | ||
trait IBirthdayService { | ||
fn wishHappyBirthday( | ||
&self, | ||
name: &str, | ||
years: i32, | ||
text: &[String], | ||
) -> binder::Result<String>; | ||
} | ||
``` | ||
|
||
<details> | ||
|
||
- Note how the `String[]` in the AIDL definition is translated as a `&[String]` | ||
in Rust, i.e. that idiomatic Rust types are used in the generated bindings | ||
wherever possible: | ||
- `in` array arguments are translated to slices. | ||
- `out` and `inout` args are translated to `&mut Vec<T>`. | ||
- Return values are translated to returning a `Vec<T>`. | ||
|
||
</details> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope people don't start doing this in their production code. Otoh I'm not sure it's worth talking about
anyhow
andthiserror
here.