-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
129 lines (107 loc) · 3.65 KB
/
main.go
File metadata and controls
129 lines (107 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Register a Go binder service using a generated AIDL stub.
//
// Same functionality as server_service (ping + echo), but uses the
// generated IPingService proxy and stub from com/example/ipingservice.go
// instead of raw OnTransaction + WriteString16. The AIDL source is at
// tools/pkg/3rdparty/examples/aidl/com/example/IPingService.aidl.
//
// Build:
//
// GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o build/server_service_aidl ./examples/server_service_aidl/
// adb push build/server_service_aidl /data/local/tmp/ && adb shell /data/local/tmp/server_service_aidl
package main
import (
"context"
"errors"
"fmt"
"os"
"github.com/AndroidGoLab/binder/binder"
"github.com/AndroidGoLab/binder/binder/versionaware"
"github.com/AndroidGoLab/binder/com/example"
aidlerrors "github.com/AndroidGoLab/binder/errors"
"github.com/AndroidGoLab/binder/kernelbinder"
"github.com/AndroidGoLab/binder/servicemanager"
)
const serviceName = "com.example.ping"
// pingImpl implements the generated IPingServiceServer interface.
type pingImpl struct{}
func (p *pingImpl) Ping(ctx context.Context) (string, error) {
return "pong", nil
}
func (p *pingImpl) Echo(ctx context.Context, message string) (string, error) {
return message, nil
}
func main() {
ctx := context.Background()
driver, err := kernelbinder.Open(ctx, binder.WithMapSize(128*1024))
if err != nil {
fmt.Fprintf(os.Stderr, "open binder: %v\n", err)
os.Exit(1)
}
defer driver.Close(ctx)
transport, err := versionaware.NewTransport(ctx, driver, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "transport: %v\n", err)
os.Exit(1)
}
sm := servicemanager.New(transport)
// Create a typed stub from our implementation.
stub := example.NewPingServiceStub(&pingImpl{})
// PingServiceStub is the TransactionReceiver for AddService.
// It dispatches incoming transactions to the IPingService implementation.
stubReceiver := &example.PingServiceStub{Impl: stub}
err = sm.AddService(ctx, servicemanager.ServiceName(serviceName), stubReceiver, false, 0)
switch {
case err == nil:
fmt.Printf("Registered service %q\n", serviceName)
remoteTest(ctx, sm)
default:
var se *aidlerrors.StatusError
if errors.As(err, &se) && se.Exception == aidlerrors.ExceptionSecurity {
fmt.Println("AddService denied by SELinux (expected from shell).")
fmt.Println("Falling back to in-process self-test.")
} else {
fmt.Fprintf(os.Stderr, "add service: %v\n", err)
fmt.Fprintf(os.Stderr, "Falling back to in-process self-test.\n\n")
}
inProcessTest(ctx, stub)
}
}
// remoteTest looks up the service and calls it through binder IPC.
func remoteTest(ctx context.Context, sm *servicemanager.ServiceManager) {
remote, err := sm.GetService(ctx, servicemanager.ServiceName(serviceName))
if err != nil {
fmt.Fprintf(os.Stderr, "get service: %v\n", err)
os.Exit(1)
}
proxy := example.NewPingServiceProxy(remote)
result, err := proxy.Ping(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "ping: %v\n", err)
os.Exit(1)
}
fmt.Printf("Ping -> %q\n", result)
result, err = proxy.Echo(ctx, "hello from Go")
if err != nil {
fmt.Fprintf(os.Stderr, "echo: %v\n", err)
os.Exit(1)
}
fmt.Printf("Echo -> %q\n", result)
fmt.Println("All remote tests passed.")
}
// inProcessTest calls the stub directly (no binder IPC).
func inProcessTest(ctx context.Context, stub example.IPingService) {
result, err := stub.Ping(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "ping: %v\n", err)
os.Exit(1)
}
fmt.Printf("Ping -> %q\n", result)
result, err = stub.Echo(ctx, "hello from Go")
if err != nil {
fmt.Fprintf(os.Stderr, "echo: %v\n", err)
os.Exit(1)
}
fmt.Printf("Echo -> %q\n", result)
fmt.Println("All in-process tests passed.")
}