Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ios/accessibility/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package accessibility

func convertToStringList(payload []interface{}) []string {
if len(payload) == 0 {
return make([]string, 0)
}
list := payload[0].([]interface{})
result := make([]string, len(list))
for i, v := range list {
Expand Down
15 changes: 15 additions & 0 deletions ios/deviceconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"time"

log "github.com/sirupsen/logrus"
plist "howett.net/plist"
)

// DeviceConnectionInterface contains a physical network connection to a usbmuxd socket.
type DeviceConnectionInterface interface {
Close() error
SendAny(message any) error
Send(message []byte) error
Reader() io.Reader
Writer() io.Writer
Expand Down Expand Up @@ -89,6 +91,19 @@ func (conn *DeviceConnection) Send(bytes []byte) error {
return nil
}

func (conn *DeviceConnection) SendAny(req any) error {
data, err := plist.Marshal(req, plist.XMLFormat)
if err != nil {
return err
}

if err := binary.Write(conn.c, binary.BigEndian, uint32(len(data))); err != nil {
return err
}

return binary.Write(conn.c, binary.BigEndian, data)
}

// Reader exposes the underlying net.Conn as io.Reader
func (conn *DeviceConnection) Reader() io.Reader {
return conn.c
Expand Down
35 changes: 35 additions & 0 deletions ios/diagnostics/diagnostics_battery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package diagnostics

import (
ios "github.com/danielpaulus/go-ios/ios"
)

type Request struct {
Request string `plist:"Request"`
}
type IORegistryRequest struct {
Request
CurrentPlane string `plist:"CurrentPlane,omitempty"`
EntryName string `plist:"EntryName,omitempty"`
EntryClass string `plist:"EntryClass,omitempty"`
}

func Battery(device ios.DeviceEntry) (interface{}, error) {
conn, _ := New(device)
req := &IORegistryRequest{
Request: Request{"IORegistry"},
CurrentPlane: "",
EntryName: "",
EntryClass: "IOPMPowerSource",
}
err := conn.deviceConn.SendAny(req)
if err != nil {
return "", err
}
respBytes, err := conn.plistCodec.RecvBytes(conn.deviceConn.Reader())
if err != nil {
return "", err
}
plist, err := ios.ParsePlist(respBytes)
return plist, err
}
37 changes: 37 additions & 0 deletions ios/dtx_codec/connection.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dtx

import (
"encoding/json"
"io"
"math"
"strings"
Expand Down Expand Up @@ -86,6 +87,42 @@ func (g GlobalDispatcher) Dispatch(msg Message) {
return
}
}
// network
v := msg.Payload[0]

b, _ := json.Marshal(v)

str := string(b)
if str == "_notifyOfPublishedCapabilities:" {
return
}

if s, ok := v.([]interface{}); ok && len(s) == 2 {
_type := s[0].(uint64)
if _type == 2 {
s1, _ := json.Marshal(s[1])
println("network:" + string(s1))
}
}
// sysmontap,cpu,meme
dataArray, ok := v.([]interface{})
if ok && len(dataArray) > 0 {
for _, ele := range dataArray {
if m, ok := ele.(map[string]interface{}); ok {
if _, ok2 := m["SystemCPUUsage"]; ok2 {
s1, _ := json.Marshal(m)
println("sysmontap:" + string(s1))
}
}
}
}

if m, ok := v.(map[string]interface{}); ok {
if b, ok2 := m["CoreAnimationFramesPerSecond"]; ok2 {
println("fps:", b.(uint64))
}
}

log.Tracef("Global Dispatcher Received: %s %s", msg.Payload, msg.Auxiliary)
if msg.HasError() {
log.Error(msg.Payload[0])
Expand Down
3 changes: 3 additions & 0 deletions ios/instruments/instruments_channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const (
procControlChannel = "com.apple.instruments.server.services.processcontrol"
procControlPosixSpawnChannel = "com.apple.instruments.server.services.processcontrol.posixspawn"
mobileNotificationsChannel = "com.apple.instruments.server.services.mobilenotifications"
mobileNetworkingChannel = "com.apple.instruments.server.services.networking"
SysmontapChannel = "com.apple.instruments.server.services.sysmontap" // 获取性能数据用
GraphicsOpenGlChannel = "com.apple.instruments.server.services.graphics.opengl"
)

const appListingChannel = "com.apple.instruments.server.services.device.applictionListing"
Expand Down
28 changes: 28 additions & 0 deletions ios/instruments/instruments_graphics_opengl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package instruments

import (
"time"

"github.com/danielpaulus/go-ios/ios"
log "github.com/sirupsen/logrus"
)

func IterOpenglData(device ios.DeviceEntry) (func() (map[string]interface{}, error), func() error, error) {
conn, err := connectInstruments(device)
if err != nil {
return nil, nil, err
}
channel := conn.RequestChannelIdentifier(GraphicsOpenGlChannel, channelDispatcher{})

resp, err := channel.MethodCall("startSamplingAtTimeInterval:", 0)
if err != nil {
log.Errorf("resp:%+v", resp)
return nil, nil, err
}
time.Sleep(time.Duration(5) * time.Second)
channel.MethodCall("stopSampling:")
conn.Close()
// return dispatcher.Receive, dispatcher.Close, nil
return nil, nil, nil

}
78 changes: 78 additions & 0 deletions ios/instruments/instruments_network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package instruments

import (
"time"

"github.com/danielpaulus/go-ios/ios"
log "github.com/sirupsen/logrus"
)

// type channelDispatcher2 struct {
// messageChannel chan dtx.Message
// closeChannel chan struct{}
// }

// func (dispatcher channelDispatcher2) Receive() (map[string]interface{}, error) {
// log.Println("--->channelDispatcher2.Receive")
// for {
// fmt.Println("---1")
// select {
// case msg := <-dispatcher.messageChannel:
// fmt.Println("---2")
// selector, result, err := toMap(msg)
// if "applicationStateNotification:" == selector && err == nil {
// return result, nil
// }
// if err != nil {
// log.Debugf("error extracting message %+v, %v", msg, err)
// }
// case <-dispatcher.closeChannel:
// fmt.Println("---4")
// return map[string]interface{}{}, io.EOF
// }
// fmt.Println("---3")
// }
// }

// func (dispatcher *channelDispatcher2) Close() error {
// select {
// case dispatcher.closeChannel <- struct{}{}:
// return nil
// case <-time.After(time.Second * 5):
// return fmt.Errorf("timeout")
// }
// }

// func (dispatcher channelDispatcher2) Dispatch(msg dtx.Message) {
// fmt.Println("---2---Dispatch")
// dispatcher.messageChannel <- msg
// }

func ListenNetwork(device ios.DeviceEntry) (func() (map[string]interface{}, error), func() error, error) {
conn, err := connectInstruments(device)
if err != nil {
return nil, nil, err
}
// dispatcher := channelDispatcher2{messageChannel: make(chan dtx.Message), closeChannel: make(chan struct{})}
// conn.AddDefaultChannelReceiver(dispatcher)

// capabs := map[string]interface{}{
// "com.apple.private.DTXBlockCompression": uint64(2),
// "com.apple.private.DTXConnection": uint64(1),
// }

// conn.GlobalChannel().MethodCall("_notifyOfPublishedCapabilities:", capabs)

channel := conn.RequestChannelIdentifier(mobileNetworkingChannel, channelDispatcher{})

resp, err := channel.MethodCall("startMonitoring")
if err != nil {
log.Errorf("resp:%+v", resp)
return nil, nil, err
}
time.Sleep(time.Duration(5) * time.Second)
conn.Close()
// return dispatcher.Receive, dispatcher.Close, nil
return nil, nil, nil

}
103 changes: 103 additions & 0 deletions ios/instruments/instruments_sysmontap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package instruments

import (
"fmt"
"time"

"github.com/danielpaulus/go-ios/ios"
)

type PerfOptions struct {

// system
SysCPU bool `json:"sys_cpu,omitempty" yaml:"sys_cpu,omitempty"`
SysMem bool `json:"sys_mem,omitempty" yaml:"sys_mem,omitempty"`
SysDisk bool `json:"sys_disk,omitempty" yaml:"sys_disk,omitempty"`
SysNetwork bool `json:"sys_network,omitempty" yaml:"sys_network,omitempty"`
gpu bool
FPS bool `json:"fps,omitempty" yaml:"fps,omitempty"`
Network bool `json:"network,omitempty" yaml:"network,omitempty"`
// process
BundleID string `json:"bundle_id,omitempty" yaml:"bundle_id,omitempty"`
Pid int `json:"pid,omitempty" yaml:"pid,omitempty"`
// config
OutputInterval int `json:"output_interval,omitempty" yaml:"output_interval,omitempty"` // ms
SystemAttributes []string `json:"system_attributes,omitempty" yaml:"system_attributes,omitempty"`
ProcessAttributes []string `json:"process_attributes,omitempty" yaml:"process_attributes,omitempty"`
}

func defaulPerfOption() *PerfOptions {
return &PerfOptions{
SysCPU: false,
SysMem: false,
SysDisk: false,
SysNetwork: false,
gpu: false,
FPS: false,
Network: false,
OutputInterval: 1000, // default 1000ms
// SystemAttributes: []string{"vmExtPageCount", "vmFreeCount", "vmPurgeableCount", "vmSpeculativeCount", "physMemSize"},
// ProcessAttributes: []string{"memVirtualSize", "cpuUsage", "ctxSwitch", "intWakeups", "physFootprint", "memResidentSize", "memAnon", "pid"},
SystemAttributes: []string{
// disk
"diskBytesRead",
"diskBytesWritten",
"diskReadOps",
"diskWriteOps",
// memory
"vmCompressorPageCount",
"vmExtPageCount",
"vmFreeCount",
"vmIntPageCount",
"vmPurgeableCount",
"vmWireCount",
"vmUsedCount",
"__vmSwapUsage",
// network
"netBytesIn",
"netBytesOut",
"netPacketsIn",
"netPacketsOut",
},
ProcessAttributes: []string{
"pid",
"cpuUsage",
},
}
}

func ListenSysmontap(device ios.DeviceEntry) (func() (map[string]interface{}, error), func() error, error) {
conn, err := connectInstruments(device)
if err != nil {
return nil, nil, err
}

channel := conn.RequestChannelIdentifier(SysmontapChannel, channelDispatcher{})
options := defaulPerfOption()
// interval := time.Millisecond * time.Duration(options.OutputInterval)
// config := map[string]interface{}{
// "bm": 0,
// "cpuUsage": true,
// "procAttrs": []string{"memVirtualSize", "cpuUsage", "ctxSwitch", "intWakeups", "physFootprint", "memResidentSize", "memAnon", "pid"},
// "sampleInterval": interval,
// "sysAttrs": []string{"vmExtPageCount", "vmFreeCount", "vmPurgeableCount", "vmSpeculativeCount", "physMemSize"},
// "ur": 1000,
// }
config := map[string]interface{}{
"bm": 0,
"cpuUsage": true,
"sampleInterval": options.OutputInterval, // time.Duration
"ur": options.OutputInterval, // 输出频率
"procAttrs": options.ProcessAttributes, // process performance
"sysAttrs": options.SystemAttributes, // system performance
}
channel.MethodCall("setConfig:", config)
channel.MethodCall("start")

time.Sleep(time.Duration(3) * time.Second)
channel.MethodCall("stop")
conn.Close()
fmt.Println("conn.Close")
return nil, nil, nil

}
14 changes: 14 additions & 0 deletions ios/plistcodec.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ func (plistCodec PlistCodec) Decode(r io.Reader) ([]byte, error) {
return payloadBytes, nil
}

func (p *PlistCodec) RecvBytes(r io.Reader) ([]byte, error) {
size := uint32(0)
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return nil, err
}

data := make([]byte, size)
if _, err := io.ReadFull(r, data); err != nil {
return nil, err
}

return data, nil
}

// PlistCodecReadWriter handles length encoded plist messages
// Each message starts with an uint32 value representing the length of the encoded payload
// followed by the binary encoded plist data
Expand Down
Loading