diff --git a/device.go b/device.go index 91aca98..3a8c1c7 100644 --- a/device.go +++ b/device.go @@ -637,133 +637,6 @@ func (d *device) MoveCrashReport(hostDir string, opts ...CrashReportMoverOption) return d.crashReportMover.Move(hostDir, opts...) } -func (d *device) GetPerfmon(opts *PerfmonOption) (out chan interface{}, outCancel context.CancelFunc, perfErr error) { - if d.lockdown == nil { - if _, err := d.lockdownService(); err != nil { - return nil, nil, err - } - } - if opts == nil { - return nil, nil, fmt.Errorf("parameter is empty") - } - if !opts.OpenChanCPU && !opts.OpenChanMEM && !opts.OpenChanGPU && !opts.OpenChanFPS && !opts.OpenChanNetWork { - opts.OpenChanCPU = true - opts.OpenChanMEM = true - opts.OpenChanGPU = true - opts.OpenChanFPS = true - opts.OpenChanNetWork = true - } - - var err error - - var instruments Instruments - ctx, cancel := context.WithCancel(context.Background()) - - chanCPU := make(chan CPUData) - chanMEM := make(chan MemData) - var cancelSysmontap context.CancelFunc - - if opts.OpenChanCPU || opts.OpenChanMEM { - instruments, err = d.lockdown.InstrumentsService() - if err != nil { - return nil, cancel, err - } - chanCPU, chanMEM, cancelSysmontap, err = instruments.StartSysmontapServer(opts.PID, ctx) - if err != nil { - cancelSysmontap() - return nil, cancel, err - } - } - - chanFPS := make(chan FPSData) - chanGPU := make(chan GPUData) - var cancelOpengl context.CancelFunc - - if opts.OpenChanGPU || opts.OpenChanFPS { - instruments, err = d.lockdown.InstrumentsService() - if err != nil { - return nil, cancel, err - } - chanFPS, chanGPU, cancelOpengl, err = instruments.StartOpenglServer(ctx) - if err != nil { - cancelOpengl() - return nil, cancel, err - } - } - - chanNetWork := make(chan NetworkData) - var cancelNetWork context.CancelFunc - if opts.OpenChanNetWork { - instruments, err = d.lockdown.InstrumentsService() - if err != nil { - return nil, cancel, err - } - chanNetWork, cancelNetWork, err = instruments.StartNetWorkingServer(ctx) - if err != nil { - cancelNetWork() - return nil, cancel, err - } - } - // 弃用之前的PerfMonData ,统一汇总到interface里,由用户自行决定处理数据 - result := make(chan interface{}) - go func() { - for { - select { - case v, ok := <-chanCPU: - if opts.OpenChanCPU && ok { - result <- v - } - case v, ok := <-chanMEM: - if opts.OpenChanMEM && ok { - result <- v - } - case v, ok := <-chanFPS: - if opts.OpenChanFPS && ok { - result <- v - } - case v, ok := <-chanGPU: - if opts.OpenChanGPU && ok { - result <- v - } - case v, ok := <-chanNetWork: - if opts.OpenChanNetWork && ok { - result <- v - } - case <-ctx.Done(): - err := d.stopPerfmon(opts) - if err != nil { - fmt.Println(err) - } - close(result) - return - } - } - }() - return result, cancel, err -} - -func (d *device) stopPerfmon(opts *PerfmonOption) (err error) { - if _, err = d.instrumentsService(); err != nil { - return err - } - if opts.OpenChanCPU || opts.OpenChanMEM { - if err = d.instruments.StopSysmontapServer(); err != nil { - return err - } - } - if opts.OpenChanGPU || opts.OpenChanFPS { - if err = d.instruments.StopOpenglServer(); err != nil { - return err - } - } - if opts.OpenChanNetWork { - if err = d.instruments.StopNetWorkingServer(); err != nil { - return err - } - } - return nil -} - func (d *device) XCTest(bundleID string, opts ...XCTestOption) (out <-chan string, cancel context.CancelFunc, err error) { xcTestOpt := defaultXCTestOption() for _, fn := range opts { diff --git a/device_test.go b/device_test.go index 716a4de..ac18e95 100644 --- a/device_test.go +++ b/device_test.go @@ -1,7 +1,6 @@ package giDevice import ( - "encoding/json" "fmt" "os" "os/signal" @@ -69,7 +68,7 @@ func Test_device_SavePairRecord(t *testing.T) { func Test_device_XCTest(t *testing.T) { setupLockdownSrv(t) - bundleID = "com.DataMesh.CheckList" + bundleID = "com.leixipaopao.WebDriverAgentRunner.xctrunner" out, cancel, err := dev.XCTest(bundleID) // out, cancel, err := dev.XCTest(bundleID, WithXCTestEnv(map[string]interface{}{"USE_PORT": 8222, "MJPEG_SERVER_PORT": 8333})) if err != nil { @@ -155,51 +154,6 @@ func Test_device_Shutdown(t *testing.T) { dev.Shutdown() } -func Test_device_Perf(t *testing.T) { - //setupDevice(t) - //SetDebug(true,true) - setupLockdownSrv(t) - - c := make(chan os.Signal) - signal.Notify(c, os.Interrupt, os.Kill) - - var opts = &PerfmonOption{ - //PID: "0", - OpenChanNetWork: true, - // OpenChanFPS: true, - // OpenChanMEM: true, - //OpenChanCPU: true, - //OpenChanGPU: true, - } - - outData, cannel, err := dev.GetPerfmon(opts) - if err != nil { - fmt.Println(err) - os.Exit(0) - } - var timeLast = time.Now().Unix() - for { - select { - case <-c: - if cannel != nil { - cannel() - } - default: - data, ok := <-outData - if !ok { - fmt.Println("end get perfmon data") - return - } - result, _ := json.MarshalIndent(data, "", "\t") - fmt.Println(string(result)) - if time.Now().Unix()-timeLast > 60 { - cannel() - } - } - } - -} - func Test_device_InstallationProxyBrowse(t *testing.T) { setupDevice(t) diff --git a/idevice.go b/idevice.go index 286baf5..a62a655 100644 --- a/idevice.go +++ b/idevice.go @@ -77,8 +77,6 @@ type Device interface { GetIconPNGData(bundleId string) (raw *bytes.Buffer, err error) GetInterfaceOrientation() (orientation OrientationState, err error) - GetPerfmon(opts *PerfmonOption) (out chan interface{}, outCancel context.CancelFunc, perfErr error) - PerfStart(opts ...PerfOption) (data <-chan []byte, err error) PerfStop() } @@ -157,19 +155,6 @@ type Instruments interface { // SysMonStart(cfg ...interface{}) (_ interface{}, err error) registerCallback(obj string, cb func(m libimobiledevice.DTXMessageResult)) - - StartOpenglServer(ctx context.Context) (chanFPS chan FPSData, chanGPU chan GPUData, cancel context.CancelFunc, err error) - - StopOpenglServer() (err error) - - StartSysmontapServer(pid string, ctx context.Context) (chanCPU chan CPUData, chanMem chan MemData, cancel context.CancelFunc, err error) - - StopSysmontapServer() (err error) - //ProcessNetwork(pid int) (out <-chan interface{}, cancel context.CancelFunc, err error) - - StartNetWorkingServer(ctx context.Context) (chanNetWorking chan NetworkData, cancel context.CancelFunc, err error) - - StopNetWorkingServer() (err error) } type Testmanagerd interface { @@ -379,15 +364,6 @@ func WithUpdateToken(updateToken string) AppListOption { } } -type PerfmonOption struct { - PID string - OpenChanGPU bool - OpenChanFPS bool - OpenChanCPU bool - OpenChanMEM bool - OpenChanNetWork bool -} - type Process struct { IsApplication bool `json:"isApplication"` Name string `json:"name"` diff --git a/instruments.go b/instruments.go index d194dbc..769873c 100644 --- a/instruments.go +++ b/instruments.go @@ -1,10 +1,8 @@ package giDevice import ( - "context" "encoding/json" "fmt" - "time" "github.com/electricbubble/gidevice/pkg/libimobiledevice" ) @@ -276,333 +274,6 @@ func (i *instruments) registerCallback(obj string, cb func(m libimobiledevice.DT i.client.RegisterCallback(obj, cb) } -func (i *instruments) StartSysmontapServer(pid string, ctxParent context.Context) ( - chanCPU chan CPUData, chanMem chan MemData, cancel context.CancelFunc, err error) { - - var id uint32 - if ctxParent == nil { - return nil, nil, nil, fmt.Errorf("missing context") - } - ctx, cancelFunc := context.WithCancel(ctxParent) - _outMEM := make(chan MemData) - _outCPU := make(chan CPUData) - if id, err = i.requestChannel(instrumentsServiceSysmontap); err != nil { - return nil, nil, cancelFunc, err - } - - selector := "setConfig:" - args := libimobiledevice.NewAuxBuffer() - - var config map[string]interface{} - config = make(map[string]interface{}) - { - config["bm"] = 0 - config["cpuUsage"] = true - - config["procAttrs"] = []string{ - "memVirtualSize", "cpuUsage", "ctxSwitch", "intWakeups", - "physFootprint", "memResidentSize", "memAnon", "pid"} - - config["sampleInterval"] = 1000000000 - // 系统信息字段 - config["sysAttrs"] = []string{ - "vmExtPageCount", "vmFreeCount", "vmPurgeableCount", - "vmSpeculativeCount", "physMemSize"} - // 刷新频率 - config["ur"] = 1000 - } - - args.AppendObject(config) - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return nil, nil, cancelFunc, err - } - selector = "start" - args = libimobiledevice.NewAuxBuffer() - - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return nil, nil, cancelFunc, err - } - - i.registerCallback("", func(m libimobiledevice.DTXMessageResult) { - select { - case <-ctx.Done(): - return - default: - mess := m.Obj - chanCPUAndMEMData(mess, _outMEM, _outCPU, pid) - } - }) - - go func() { - i.registerCallback("_Golang-iDevice_Over", func(_ libimobiledevice.DTXMessageResult) { - cancelFunc() - }) - select { - case <-ctx.Done(): - var isOpen bool - if _outCPU != nil { - _, isOpen = <-_outMEM - if isOpen { - close(_outMEM) - } - } - if _outMEM != nil { - _, isOpen = <-_outCPU - if isOpen { - close(_outCPU) - } - } - } - return - }() - return _outCPU, _outMEM, cancelFunc, err -} - -func chanCPUAndMEMData(mess interface{}, _outMEM chan MemData, _outCPU chan CPUData, pid string) { - switch mess.(type) { - case []interface{}: - var infoCPU CPUData - var infoMEM MemData - messArray := mess.([]interface{}) - if len(messArray) == 2 { - var sinfo = messArray[0].(map[string]interface{}) - var pinfolist = messArray[1].(map[string]interface{}) - if sinfo["CPUCount"] == nil { - var temp = sinfo - sinfo = pinfolist - pinfolist = temp - } - if sinfo["CPUCount"] != nil && pinfolist["Processes"] != nil { - var cpuCount = sinfo["CPUCount"] - var sysCpuUsage = sinfo["SystemCPUUsage"].(map[string]interface{}) - var cpuTotalLoad = sysCpuUsage["CPU_TotalLoad"] - // 构建返回信息 - infoCPU.CPUCount = int(cpuCount.(uint64)) - infoCPU.SysCPUUsageTotalLoad = cpuTotalLoad.(float64) - //finalCpuInfo["attrCpuTotal"] = cpuTotalLoad - - var cpuUsage = 0.0 - pidMess := pinfolist["Processes"].(map[string]interface{})[pid] - if pidMess != nil { - processInfo := convertProcessData(pidMess) - cpuUsage = processInfo["cpuUsage"].(float64) - infoCPU.ProcCPUUsage = cpuUsage - infoCPU.ProcPID = pid - infoCPU.ProcAttrCtxSwitch = convert2Int64(processInfo["ctxSwitch"]) - infoCPU.ProcAttrIntWakeups = convert2Int64(processInfo["intWakeups"]) - - infoMEM.Vss = convert2Int64(processInfo["memVirtualSize"]) - infoMEM.Rss = convert2Int64(processInfo["memResidentSize"]) - infoMEM.Anon = convert2Int64(processInfo["memAnon"]) - infoMEM.PhysMemory = convert2Int64(processInfo["physFootprint"]) - - } else { - infoCPU.Msg = "invalid PID" - infoMEM.Msg = "invalid PID" - - infoMEM.Vss = -1 - infoMEM.Rss = -1 - infoMEM.Anon = -1 - infoMEM.PhysMemory = -1 - } - - infoMEM.TimeStamp = time.Now().UnixNano() - infoCPU.TimeStamp = time.Now().UnixNano() - - _outMEM <- infoMEM - _outCPU <- infoCPU - } - } - } -} - -func (i *instruments) StopSysmontapServer() (err error) { - id, err := i.requestChannel(instrumentsServiceSysmontap) - if err != nil { - return err - } - selector := "stop" - args := libimobiledevice.NewAuxBuffer() - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return err - } - return nil -} - -// todo 获取单进程流量情况,看情况做不做 -// 目前只获取到系统全局的流量情况,单进程需要用到set,go没有,并且实际用python测试单进程的流量情况不准 -func (i *instruments) StartNetWorkingServer(ctxParent context.Context) (chanNetWorking chan NetworkData, cancel context.CancelFunc, err error) { - var id uint32 - if ctxParent == nil { - return nil, nil, fmt.Errorf("missing context") - } - ctx, cancelFunc := context.WithCancel(ctxParent) - _outNetWork := make(chan NetworkData) - if id, err = i.requestChannel(instrumentsServiceNetworking); err != nil { - return nil, cancelFunc, err - } - selector := "startMonitoring" - args := libimobiledevice.NewAuxBuffer() - - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return nil, cancelFunc, err - } - i.registerCallback("", func(m libimobiledevice.DTXMessageResult) { - select { - case <-ctx.Done(): - return - default: - receData, ok := m.Obj.([]interface{}) - if ok && len(receData) == 2 { - sendAndReceiveData, ok := receData[1].([]interface{}) - if ok { - var netData NetworkData - // 有时候是uint8,有时候是uint64。。。恶心 - netData.RxBytes = convert2Int64(sendAndReceiveData[0]) - netData.RxPackets = convert2Int64(sendAndReceiveData[1]) - netData.TxBytes = convert2Int64(sendAndReceiveData[2]) - netData.TxPackets = convert2Int64(sendAndReceiveData[3]) - netData.TimeStamp = time.Now().UnixNano() - _outNetWork <- netData - } - } - } - }) - go func() { - i.registerCallback("_Golang-iDevice_Over", func(_ libimobiledevice.DTXMessageResult) { - cancelFunc() - }) - select { - case <-ctx.Done(): - _, isOpen := <-_outNetWork - if isOpen { - close(_outNetWork) - } - } - return - }() - return _outNetWork, cancelFunc, err -} - -func (i *instruments) StopNetWorkingServer() (err error) { - var id uint32 - id, err = i.requestChannel(instrumentsServiceNetworking) - if err != nil { - return err - } - selector := "stopMonitoring" - args := libimobiledevice.NewAuxBuffer() - - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return err - } - return nil -} - -func (i *instruments) StartOpenglServer(ctxParent context.Context) (chanFPS chan FPSData, chanGPU chan GPUData, cancel context.CancelFunc, err error) { - var id uint32 - if ctxParent == nil { - return nil, nil, nil, fmt.Errorf("missing context") - } - ctx, cancelFunc := context.WithCancel(ctxParent) - _outFPS := make(chan FPSData) - _outGPU := make(chan GPUData) - if id, err = i.requestChannel(instrumentsServiceGraphicsOpengl); err != nil { - return nil, nil, cancelFunc, err - } - - selector := "availableStatistics" - args := libimobiledevice.NewAuxBuffer() - - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return nil, nil, cancelFunc, err - } - - selector = "setSamplingRate:" - if err = args.AppendObject(0.0); err != nil { - return nil, nil, cancelFunc, err - } - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return nil, nil, cancelFunc, err - } - - selector = "startSamplingAtTimeInterval:processIdentifier:" - args = libimobiledevice.NewAuxBuffer() - if err = args.AppendObject(0); err != nil { - return nil, nil, cancelFunc, err - } - if err = args.AppendObject(0); err != nil { - return nil, nil, cancelFunc, err - } - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return nil, nil, cancelFunc, err - } - - i.registerCallback("", func(m libimobiledevice.DTXMessageResult) { - select { - case <-ctx.Done(): - return - default: - mess := m.Obj - var deviceUtilization = mess.(map[string]interface{})["Device Utilization %"] // Device Utilization - var tilerUtilization = mess.(map[string]interface{})["Tiler Utilization %"] // Tiler Utilization - var rendererUtilization = mess.(map[string]interface{})["Renderer Utilization %"] // Renderer Utilization - - var infoGPU GPUData - - infoGPU.DeviceUtilization = convert2Int64(deviceUtilization) - infoGPU.TilerUtilization = convert2Int64(tilerUtilization) - infoGPU.RendererUtilization = convert2Int64(rendererUtilization) - infoGPU.TimeStamp = time.Now().UnixNano() - _outGPU <- infoGPU - - var infoFPS FPSData - var fps = mess.(map[string]interface{})["CoreAnimationFramesPerSecond"] - infoFPS.FPS = int(convert2Int64(fps)) - infoFPS.TimeStamp = time.Now().UnixNano() - _outFPS <- infoFPS - } - }) - go func() { - i.registerCallback("_Golang-iDevice_Over", func(_ libimobiledevice.DTXMessageResult) { - cancelFunc() - }) - select { - case <-ctx.Done(): - var isOpen bool - if _outGPU != nil { - _, isOpen = <-_outGPU - if isOpen { - close(_outGPU) - } - } - if _outFPS != nil { - _, isOpen = <-_outFPS - if isOpen { - close(_outFPS) - } - } - } - return - }() - return _outFPS, _outGPU, cancelFunc, err -} - -func (i *instruments) StopOpenglServer() (err error) { - - id, err := i.requestChannel(instrumentsServiceGraphicsOpengl) - if err != nil { - return err - } - selector := "stop" - args := libimobiledevice.NewAuxBuffer() - - if _, err = i.client.Invoke(selector, args, id, true); err != nil { - return err - } - return nil -} - type Application struct { AppExtensionUUIDs []string `json:"AppExtensionUUIDs,omitempty"` BundlePath string `json:"BundlePath"` diff --git a/instruments_test.go b/instruments_test.go index 98bf203..8e208e6 100644 --- a/instruments_test.go +++ b/instruments_test.go @@ -22,7 +22,7 @@ func setupInstrumentsSrv(t *testing.T) { func Test_instruments_AppLaunch(t *testing.T) { setupInstrumentsSrv(t) - bundleID = "com.DataMesh.CheckList" + // bundleID = "com.leixipaopao.WebDriverAgentRunner.xctrunner" // pid, err := dev.AppLaunch(bundleID) pid, err := instrumentsSrv.AppLaunch(bundleID)