Skip to content

Commit 11bece1

Browse files
committed
docs: fix Go syntax in README snippets, add missing examples, implement overlay specs
Fix invalid Go syntax in Toggle Flashlight and Server-Side Service README snippets where method declarations appeared inside function-body context. Split into separate code blocks with type definitions at top level. Add Query Battery Level and Send a Raw Binder Transaction usage examples to address documentation gaps. Add collapsible "Using other services" guide for working with any binder service. Implement overlay spec support: ReadAllSpecs now merges overlay.yaml entries on top of auto-generated spec.yaml. Add auto-generated header comment to WritePackageSpec. Create servicemanager overlay with 5 service entries (batteryproperties, media.camera, mount, package, package_native). Replace all magic service name strings in examples with generated servicemanager constants. Minor cleanups: strings.Split instead of custom splitLines, stderr for error output.
1 parent 2b10575 commit 11bece1

19 files changed

Lines changed: 475 additions & 79 deletions

File tree

README.md

Lines changed: 146 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -294,25 +294,37 @@ Requires `android.permission.CAMERA`; see [`examples/flashlight_torch/`](example
294294

295295
```go
296296
import (
297+
"context"
298+
297299
"github.com/AndroidGoLab/binder/android/hardware"
298300
"github.com/AndroidGoLab/binder/binder"
299301
"github.com/AndroidGoLab/binder/parcel"
300302
"github.com/AndroidGoLab/binder/servicemanager"
301303
)
302304

303-
svc, err := sm.GetService(ctx, servicemanager.ServiceName("media.camera"))
305+
// torchToken is a minimal TransactionReceiver for SetTorchMode's client binder.
306+
type torchToken struct{}
307+
308+
func (t *torchToken) Descriptor() string { return "torch.client" }
309+
310+
func (t *torchToken) OnTransaction(
311+
_ context.Context,
312+
_ binder.TransactionCode,
313+
_ *parcel.Parcel,
314+
) (*parcel.Parcel, error) {
315+
return parcel.New(), nil
316+
}
317+
```
318+
319+
```go
320+
svc, err := sm.GetService(ctx, servicemanager.MediaCameraService)
304321
if err != nil {
305322
log.Fatal(err)
306323
}
307324
camera := hardware.NewCameraServiceProxy(svc)
308325

309326
// The camera service requires a non-null client binder token.
310-
type token struct{}
311-
func (t *token) Descriptor() string { return "torch.client" }
312-
func (t *token) OnTransaction(_ context.Context, _ binder.TransactionCode, _ *parcel.Parcel) (*parcel.Parcel, error) {
313-
return parcel.New(), nil
314-
}
315-
clientToken := binder.NewStubBinder(&token{})
327+
clientToken := binder.NewStubBinder(&torchToken{})
316328
clientToken.RegisterWithTransport(ctx, transport)
317329

318330
// Turn torch on for camera "0"
@@ -333,7 +345,7 @@ import (
333345
"github.com/AndroidGoLab/binder/servicemanager"
334346
)
335347

336-
svc, err := sm.GetService(ctx, servicemanager.ServiceName("package"))
348+
svc, err := sm.GetService(ctx, servicemanager.PackageService)
337349
if err != nil {
338350
log.Fatal(err)
339351
}
@@ -360,7 +372,7 @@ import (
360372
)
361373

362374
// Non-blocking service check (returns nil if not found)
363-
svc, err := sm.CheckService(ctx, servicemanager.ServiceName("media.camera"))
375+
svc, err := sm.CheckService(ctx, servicemanager.MediaCameraService)
364376
if err != nil {
365377
log.Fatal(err)
366378
}
@@ -384,7 +396,37 @@ import (
384396
}
385397
```
386398

387-
### Register a Server-Side Service
399+
### Query Battery Level
400+
401+
```go
402+
import (
403+
"github.com/AndroidGoLab/binder/android/hardware/health"
404+
"github.com/AndroidGoLab/binder/servicemanager"
405+
)
406+
407+
svc, err := sm.GetService(ctx, servicemanager.ServiceName(health.DescriptorIHealth+"/default"))
408+
if err != nil {
409+
log.Fatal(err)
410+
}
411+
h := health.NewHealthProxy(svc)
412+
413+
capacity, err := h.GetCapacity(ctx)
414+
if err != nil {
415+
log.Fatal(err)
416+
}
417+
fmt.Printf("Battery level: %d%%\n", capacity)
418+
419+
info, err := h.GetHealthInfo(ctx)
420+
if err != nil {
421+
log.Fatal(err)
422+
}
423+
fmt.Printf("Status: %v, Temperature: %.1f °C\n",
424+
info.BatteryStatus, float64(info.BatteryTemperatureTenthsCelsius)/10)
425+
fmt.Printf("Voltage: %d mV, Current: %d µA\n",
426+
info.BatteryVoltageMillivolts, info.BatteryCurrentMicroamps)
427+
```
428+
429+
### Send a Raw Binder Transaction
388430

389431
```go
390432
import (
@@ -393,26 +435,106 @@ import (
393435
"github.com/AndroidGoLab/binder/servicemanager"
394436
)
395437

396-
// Implement the TransactionReceiver interface
397-
type myService struct{}
438+
svc, err := sm.GetService(ctx, servicemanager.ActivityService)
439+
if err != nil {
440+
log.Fatal(err)
441+
}
398442

399-
func (s *myService) Descriptor() string { return "com.example.IPingService" }
443+
// Build the request parcel.
444+
data := parcel.New()
445+
defer data.Recycle()
446+
data.WriteInterfaceToken("android.app.IActivityManager")
447+
data.WriteString16("android.permission.INTERNET")
448+
data.WriteInt32(int32(os.Getpid()))
449+
data.WriteInt32(int32(os.Getuid()))
400450

401-
func (s *myService) OnTransaction(
402-
ctx context.Context,
403-
code binder.TransactionCode,
404-
data *parcel.Parcel,
405-
) (*parcel.Parcel, error) {
406-
reply := parcel.New()
407-
binder.WriteStatus(reply, nil)
408-
reply.WriteString16("pong")
409-
return reply, nil
451+
// Resolve the method's transaction code and send.
452+
code, err := svc.ResolveCode(ctx, "android.app.IActivityManager", "checkPermission")
453+
if err != nil {
454+
log.Fatal(err)
455+
}
456+
reply, err := svc.Transact(ctx, code, 0, data)
457+
if err != nil {
458+
log.Fatal(err)
410459
}
460+
defer reply.Recycle()
411461

462+
// Read the AIDL status header, then the return value.
463+
if err := binder.ReadStatus(reply); err != nil {
464+
log.Fatal(err)
465+
}
466+
result, _ := reply.ReadInt32()
467+
fmt.Printf("checkPermission returned: %d\n", result)
468+
```
469+
470+
### Register a Server-Side Service
471+
472+
```go
473+
import (
474+
"context"
475+
476+
"github.com/AndroidGoLab/binder/binder"
477+
"github.com/AndroidGoLab/binder/parcel"
478+
"github.com/AndroidGoLab/binder/servicemanager"
479+
)
480+
481+
// myService implements binder.TransactionReceiver for a simple ping service.
482+
type myService struct{}
483+
484+
func (s *myService) Descriptor() string { return "com.example.IPingService" }
485+
486+
func (s *myService) OnTransaction(
487+
ctx context.Context,
488+
code binder.TransactionCode,
489+
data *parcel.Parcel,
490+
) (*parcel.Parcel, error) {
491+
reply := parcel.New()
492+
binder.WriteStatus(reply, nil)
493+
reply.WriteString16("pong")
494+
return reply, nil
495+
}
496+
```
497+
498+
```go
412499
// Register with ServiceManager
413500
err := sm.AddService(ctx, servicemanager.ServiceName("my.service"), &myService{}, false, 0)
414501
```
415502

503+
<details>
504+
<summary><strong>Using other services</strong></summary>
505+
506+
The examples above cover specific subsystems, but the library supports **all** Android binder services — over 1,500 interfaces. To work with a service not shown above:
507+
508+
1. **Find the service name.** Run `bindercli service list` on the device, or check `servicemanager/service_names_gen.go` for well-known constants.
509+
510+
2. **Find the generated proxy.** Browse the `android/` and `com/` packages on [pkg.go.dev](https://pkg.go.dev/github.com/AndroidGoLab/binder) or use `grep`:
511+
512+
```bash
513+
# Find the proxy for a known AIDL interface
514+
grep -r 'DescriptorI.*= "android.os.IVibratorService"' android/
515+
```
516+
517+
3. **Connect and call methods:**
518+
519+
```go
520+
svc, err := sm.GetService(ctx, servicemanager.VibratorService)
521+
if err != nil {
522+
log.Fatal(err)
523+
}
524+
proxy := genOs.NewVibratorServiceProxy(svc)
525+
result, err := proxy.SomeMethod(ctx, args...)
526+
```
527+
528+
4. **For HAL services** (hardware abstraction layers), the service name is the AIDL descriptor plus `/default`:
529+
530+
```go
531+
svc, err := sm.GetService(ctx, servicemanager.ServiceName(health.DescriptorIHealth+"/default"))
532+
```
533+
534+
5. **For services without a generated proxy**, use raw transactions (see [Send a Raw Binder Transaction](#send-a-raw-binder-transaction) above).
535+
536+
</details>
537+
416538
More examples: [`examples/`](examples/)
417539

418540
<!-- END GENERATED USAGE_EXAMPLES -->
@@ -1838,7 +1960,7 @@ git submodule update --init --depth 1
18381960
go run ./tools/cmd/aospgen -3rdparty tools/pkg/3rdparty -output . -smoke-tests
18391961
```
18401962

1841-
This discovers all AIDL files across `frameworks-base`, `frameworks-native`, `hardware-interfaces`, and `system-hardware-interfaces`, infers search roots from package declarations, and generates Go proxies for all AOSP services. The current AOSP snapshot produces **5,092 Go files** across **399 packages**.
1963+
This discovers all AIDL files across `frameworks-base`, `frameworks-native`, `hardware-interfaces`, and `system-hardware-interfaces`, infers search roots from package declarations, and generates Go proxies for all AOSP services. The current AOSP snapshot produces **5,097 Go files** across **399 packages**.
18421964

18431965
### Transaction Code Resolution
18441966

@@ -2130,7 +2252,7 @@ See the example app at [`examples/gomobile/`](examples/gomobile/).
21302252
│ └── driver.go Open, mmap, ioctl BINDER_WRITE_READ
21312253
├── servicemanager/ ServiceManager client
21322254
├── errors/ AIDL exception types (ExceptionCode, StatusError)
2133-
├── android/ Pre-generated AOSP service proxies (5,092 files)
2255+
├── android/ Pre-generated AOSP service proxies (5,097 files)
21342256
│ ├── app/ ActivityManager, AlarmManager, ...
21352257
│ ├── os/ ServiceManager, PowerManager, ...
21362258
│ ├── hardware/ HAL interfaces

android/content/pm/get_package.go

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

android/content/pm/get_package_native.go

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

android/hardware/get_media.camera.go

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

android/os/get_batteryproperties.go

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

android/os/storage/get_mount.go

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/battery_health/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func main() {
5252

5353
sm := servicemanager.New(transport)
5454

55-
svc, err := sm.GetService(ctx, servicemanager.ServiceName("batteryproperties"))
55+
svc, err := sm.GetService(ctx, servicemanager.BatteryPropertiesService)
5656
if err != nil {
5757
fmt.Fprintf(os.Stderr, "get batteryproperties service: %v\n", err)
5858
fmt.Fprintln(os.Stderr, "Falling back to sysfs...")

examples/device_info/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func main() {
160160
}
161161

162162
// Screensaver / Dreams
163-
dreamSvc, err := sm.GetService(ctx, servicemanager.ServiceName("dreams"))
163+
dreamSvc, err := sm.GetService(ctx, servicemanager.DreamService)
164164
if err == nil {
165165
dream := dreams.NewDreamManagerProxy(dreamSvc)
166166

examples/flashlight_torch/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func main() {
6262

6363
sm := servicemanager.New(transport)
6464

65-
svc, err := sm.GetService(ctx, "media.camera")
65+
svc, err := sm.GetService(ctx, servicemanager.MediaCameraService)
6666
if err != nil {
6767
fmt.Fprintf(os.Stderr, "get media.camera service: %v\n", err)
6868
os.Exit(1)

examples/getservice_vs_checkservice/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ func main() {
8484
// Open binder driver
8585
driver, err := kernelbinder.Open(ctx, binder.WithMapSize(128*1024))
8686
if err != nil {
87-
fmt.Printf("FATAL: /dev/binder open failed: %v\n", err)
87+
fmt.Fprintf(os.Stderr, "open binder: %v\n", err)
8888
os.Exit(1)
8989
}
9090
defer driver.Close(ctx)
91-
fmt.Println("/dev/binder: OPEN OK")
91+
fmt.Println("/dev/binder: OK")
9292

9393
transport, err := versionaware.NewTransport(ctx, driver, 0)
9494
if err != nil {
95-
fmt.Printf("FATAL: VersionAwareTransport failed: %v\n", err)
95+
fmt.Fprintf(os.Stderr, "version-aware transport: %v\n", err)
9696
os.Exit(1)
9797
}
9898
defer transport.Close(ctx)

0 commit comments

Comments
 (0)