Skip to content

Commit 046e7da

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
fix: softap_manage example uses INetworkManagementService instead of hostapd HAL
Replace android.hardware.wifi.hostapd.IHostapd vendor HAL with INetworkManagementService via "network_management" system service. Shows network interface list, bandwidth control status, and tethering status (where available). Documents API 36 method removals.
1 parent daea720 commit 046e7da

1 file changed

Lines changed: 45 additions & 153 deletions

File tree

examples/softap_manage/main.go

Lines changed: 45 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
// Manage SoftAP (WiFi hotspot) via the hostapd HAL.
1+
// Query network management status via the INetworkManagementService system service.
22
//
3-
// This example demonstrates how to start and stop a WiFi access point,
4-
// force-disconnect clients, and configure AP parameters using the
5-
// android.hardware.wifi.hostapd HAL interface.
3+
// Uses INetworkManagementService via the "network_management" service to
4+
// list network interfaces, check tethering and firewall/bandwidth status.
65
//
7-
// Note: The hostapd HAL is only available on devices with real WiFi hardware.
8-
// It may be blocked by SELinux for unprivileged binaries. On a real device,
9-
// run as root or with the appropriate SELinux context.
6+
// Note: Some methods require root or AID_SYSTEM, and some tethering methods
7+
// were removed in Android API 36+.
108
//
119
// Build:
1210
//
13-
// GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o build/softap_manage ./examples/softap_manage/
11+
// GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o build/softap_manage ./examples/softap_manage/
1412
// adb push softap_manage /data/local/tmp/ && adb shell /data/local/tmp/softap_manage
1513
package main
1614

@@ -19,28 +17,14 @@ import (
1917
"fmt"
2018
"os"
2119

20+
genOs "github.com/xaionaro-go/binder/android/os"
2221
"github.com/xaionaro-go/binder/binder"
2322
"github.com/xaionaro-go/binder/binder/versionaware"
24-
"github.com/xaionaro-go/binder/android/hardware/wifi/hostapd"
2523
"github.com/xaionaro-go/binder/kernelbinder"
2624
"github.com/xaionaro-go/binder/servicemanager"
2725
)
2826

29-
const halServiceName = servicemanager.ServiceName("android.hardware.wifi.hostapd.IHostapd/default")
30-
3127
func main() {
32-
if len(os.Args) < 2 {
33-
fmt.Fprintf(os.Stderr, "Usage: %s <command> [args...]\n", os.Args[0])
34-
fmt.Fprintf(os.Stderr, "\nCommands:\n")
35-
fmt.Fprintf(os.Stderr, " start <iface> <ssid> <passphrase> Start AP on interface\n")
36-
fmt.Fprintf(os.Stderr, " stop <iface> Stop AP on interface\n")
37-
fmt.Fprintf(os.Stderr, " kick <iface> <mac_hex> Disconnect a client\n")
38-
fmt.Fprintf(os.Stderr, " terminate Terminate hostapd daemon\n")
39-
fmt.Fprintf(os.Stderr, "\nExample:\n")
40-
fmt.Fprintf(os.Stderr, " %s start wlan1 MyHotspot s3cretP4ss\n", os.Args[0])
41-
os.Exit(1)
42-
}
43-
4428
ctx := context.Background()
4529

4630
driver, err := kernelbinder.Open(ctx, binder.WithMapSize(128*1024))
@@ -58,152 +42,60 @@ func main() {
5842

5943
sm := servicemanager.New(transport)
6044

61-
svc, err := sm.GetService(ctx, halServiceName)
45+
svc, err := sm.GetService(ctx, servicemanager.NetworkmanagementService)
6246
if err != nil {
63-
fmt.Fprintf(os.Stderr, "get hostapd HAL: %v\n", err)
64-
fmt.Fprintf(os.Stderr, "(hostapd HAL not available — no WiFi hardware or SELinux denial)\n")
47+
fmt.Fprintf(os.Stderr, "get network_management service: %v\n", err)
48+
fmt.Fprintf(os.Stderr, "(INetworkManagementService not available or access denied)\n")
6549
os.Exit(1)
6650
}
6751

68-
ap := hostapd.NewHostapdProxy(svc)
69-
70-
switch os.Args[1] {
71-
case "start":
72-
cmdStart(ctx, ap)
73-
case "stop":
74-
cmdStop(ctx, ap)
75-
case "kick":
76-
cmdKick(ctx, ap)
77-
case "terminate":
78-
cmdTerminate(ctx, ap)
79-
default:
80-
fmt.Fprintf(os.Stderr, "unknown command: %s\n", os.Args[1])
81-
os.Exit(1)
82-
}
83-
}
84-
85-
func cmdStart(
86-
ctx context.Context,
87-
ap *hostapd.HostapdProxy,
88-
) {
89-
if len(os.Args) < 5 {
90-
fmt.Fprintf(os.Stderr, "usage: start <iface> <ssid> <passphrase>\n")
91-
os.Exit(1)
92-
}
52+
netMgr := genOs.NewNetworkManagementServiceProxy(svc)
9353

94-
ifaceName := os.Args[2]
95-
ssid := os.Args[3]
96-
passphrase := os.Args[4]
97-
98-
ifaceParams := hostapd.IfaceParams{
99-
Name: ifaceName,
100-
HwModeParams: hostapd.HwModeParams{
101-
Enable80211N: true,
102-
Enable80211AC: true,
103-
Enable80211AX: true,
104-
},
105-
ChannelParams: []hostapd.ChannelParams{
106-
{
107-
BandMask: hostapd.BandMaskBand2Ghz,
108-
EnableAcs: true, // Let the driver pick the best channel.
109-
},
110-
},
111-
}
112-
113-
nwParams := hostapd.NetworkParams{
114-
Ssid: []byte(ssid),
115-
IsHidden: false,
116-
EncryptionType: hostapd.EncryptionTypeWpa3SaeTransition,
117-
Passphrase: passphrase,
118-
}
119-
120-
err := ap.AddAccessPoint(ctx, ifaceParams, nwParams)
54+
// Check tethering status (may be absent on API 36+).
55+
tethering, err := netMgr.IsTetheringStarted(ctx)
12156
if err != nil {
122-
fmt.Fprintf(os.Stderr, "AddAccessPoint: %v\n", err)
123-
os.Exit(1)
124-
}
125-
126-
fmt.Printf("Access point started on %s\n", ifaceName)
127-
fmt.Printf(" SSID: %s\n", ssid)
128-
fmt.Printf(" Security: WPA3-SAE Transition\n")
129-
fmt.Printf(" Band: 2.4 GHz (ACS)\n")
130-
}
131-
132-
func cmdStop(
133-
ctx context.Context,
134-
ap *hostapd.HostapdProxy,
135-
) {
136-
if len(os.Args) < 3 {
137-
fmt.Fprintf(os.Stderr, "usage: stop <iface>\n")
138-
os.Exit(1)
57+
fmt.Fprintf(os.Stderr, "IsTetheringStarted: %v\n", err)
58+
fmt.Fprintf(os.Stderr, " (this method was removed in Android API 36)\n")
59+
} else {
60+
fmt.Printf("Tethering active: %v\n", tethering)
13961
}
14062

141-
ifaceName := os.Args[2]
142-
err := ap.RemoveAccessPoint(ctx, ifaceName)
63+
// List tethered interfaces (may be absent on API 36+).
64+
tethered, err := netMgr.ListTetheredInterfaces(ctx)
14365
if err != nil {
144-
fmt.Fprintf(os.Stderr, "RemoveAccessPoint: %v\n", err)
145-
os.Exit(1)
146-
}
147-
148-
fmt.Printf("Access point stopped on %s\n", ifaceName)
149-
}
150-
151-
func cmdKick(
152-
ctx context.Context,
153-
ap *hostapd.HostapdProxy,
154-
) {
155-
if len(os.Args) < 4 {
156-
fmt.Fprintf(os.Stderr, "usage: kick <iface> <mac_hex>\n")
157-
fmt.Fprintf(os.Stderr, " mac_hex: 6-byte MAC as hex, e.g. aabbccddeeff\n")
158-
os.Exit(1)
159-
}
160-
161-
ifaceName := os.Args[2]
162-
macHex := os.Args[3]
163-
164-
mac, err := hexToBytes(macHex)
165-
if err != nil || len(mac) != 6 {
166-
fmt.Fprintf(os.Stderr, "invalid MAC address: %s (need 12 hex chars)\n", macHex)
167-
os.Exit(1)
66+
fmt.Fprintf(os.Stderr, "ListTetheredInterfaces: %v\n", err)
67+
fmt.Fprintf(os.Stderr, " (this method was removed in Android API 36)\n")
68+
} else if len(tethered) == 0 {
69+
fmt.Println("Tethered interfaces: (none)")
70+
} else {
71+
fmt.Printf("Tethered interfaces: %v\n", tethered)
16872
}
16973

170-
err = ap.ForceClientDisconnect(
171-
ctx,
172-
ifaceName,
173-
mac,
174-
hostapd.Ieee80211ReasonCodeWlanReasonDisassocApBusy,
175-
)
74+
// List all network interfaces.
75+
ifaces, err := netMgr.ListInterfaces(ctx)
17676
if err != nil {
177-
fmt.Fprintf(os.Stderr, "ForceClientDisconnect: %v\n", err)
178-
os.Exit(1)
77+
fmt.Fprintf(os.Stderr, "ListInterfaces: %v\n", err)
78+
} else {
79+
fmt.Printf("\nNetwork interfaces (%d):\n", len(ifaces))
80+
for _, iface := range ifaces {
81+
fmt.Printf(" %s\n", iface)
82+
}
17983
}
18084

181-
fmt.Printf("Disconnected client %x from %s\n", mac, ifaceName)
182-
}
183-
184-
func cmdTerminate(
185-
ctx context.Context,
186-
ap *hostapd.HostapdProxy,
187-
) {
188-
err := ap.Terminate(ctx)
85+
// Check bandwidth control.
86+
fmt.Println()
87+
bwCtrl, err := netMgr.IsBandwidthControlEnabled(ctx)
18988
if err != nil {
190-
fmt.Fprintf(os.Stderr, "Terminate: %v\n", err)
191-
os.Exit(1)
89+
fmt.Fprintf(os.Stderr, "IsBandwidthControlEnabled: %v\n", err)
90+
} else {
91+
fmt.Printf("Bandwidth control enabled: %v\n", bwCtrl)
19292
}
19393

194-
fmt.Println("hostapd daemon terminated")
195-
}
196-
197-
func hexToBytes(s string) ([]byte, error) {
198-
if len(s)%2 != 0 {
199-
return nil, fmt.Errorf("odd length hex string")
200-
}
201-
b := make([]byte, len(s)/2)
202-
for i := range b {
203-
_, err := fmt.Sscanf(s[2*i:2*i+2], "%02x", &b[i])
204-
if err != nil {
205-
return nil, err
206-
}
94+
// Check firewall status (requires AID_SYSTEM).
95+
fwEnabled, err := netMgr.IsFirewallEnabled(ctx)
96+
if err != nil {
97+
fmt.Fprintf(os.Stderr, "IsFirewallEnabled: %v (requires AID_SYSTEM)\n", err)
98+
} else {
99+
fmt.Printf("Firewall enabled: %v\n", fwEnabled)
207100
}
208-
return b, nil
209101
}

0 commit comments

Comments
 (0)