Skip to content

Commit

Permalink
Add deviceinfo service info to info command (danielpaulus#155)
Browse files Browse the repository at this point in the history
I added two new fields to the info command. The response of hardwareInformation and networkInformation from the instruments service are now in the results if a developer image is mounted.
hardWareInformation contains various cpu infos. Here is an example:
map[hwCPU64BitCapable:1 hwCPUsubtype:1 hwCPUtype:16777228 numberOfCpus:2 numberOfPhysicalCpus:2 speedOfCpus:0]

networkInformation contains a list of all network interfaces on the device. Example:
map[en0:Wi-Fi en1:Ethernet Adaptor (en1) en2:Ethernet Adaptor (en2) lo0:Loopback pdp_ip0:Cellular (pdp_ip0)
pdp_ip1:Cellular (pdp_ip1) pdp_ip2:Cellular (pdp_ip2) pdp_ip3:Cellular (pdp_ip3) pdp_ip4:Cellular (pdp_ip4)]

Those are now part of the ios info command output only if the developer image was mounted on the device.
  • Loading branch information
danielpaulus authored Aug 3, 2022
1 parent 699df0a commit 904b5af
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 44 deletions.
47 changes: 47 additions & 0 deletions ios/instruments/helper.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package instruments

import (
"fmt"
"github.com/danielpaulus/go-ios/ios"
dtx "github.com/danielpaulus/go-ios/ios/dtx_codec"
"github.com/danielpaulus/go-ios/ios/nskeyedarchiver"
log "github.com/sirupsen/logrus"
)

Expand All @@ -29,3 +31,48 @@ func connectInstruments(device ios.DeviceEntry) (*dtx.Connection, error) {
}
return dtxConn, nil
}

func toMap(msg dtx.Message) (string, map[string]interface{}, error) {
if len(msg.Payload) != 1 {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v has payload size !=1", msg)
}
selector, ok := msg.Payload[0].(string)
if !ok {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v payload: %+v wasn't a string", msg, msg.Payload[0])
}
args := msg.Auxiliary.GetArguments()
if len(args) == 0 {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v has an empty auxiliary dictionary", msg)
}

data, ok := args[0].([]byte)
if !ok {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v invalid aux", msg)
}

unarchived, err := nskeyedarchiver.Unarchive(data)
if err != nil {
return "", map[string]interface{}{}, err
}
if len(unarchived) == 0 {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v invalid aux", msg)
}

aux, ok := unarchived[0].(map[string]interface{})
if !ok {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v auxiliary: %+v didn't contain a map[string]interface{}", msg, msg.Payload[0])
}

return selector, aux, nil
}

func extractMapPayload(message dtx.Message) (map[string]interface{}, error) {
if len(message.Payload) != 1 {
return map[string]interface{}{}, fmt.Errorf("payload of message should have only one element: %+v", message)
}
response, ok := message.Payload[0].(map[string]interface{})
if !ok {
return map[string]interface{}{}, fmt.Errorf("payload type of message should be map[string]interface{}: %+v", message)
}
return response, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@ func (d DeviceInfoService) NameForPid(pid uint64) error {
return err
}

// HardwareInformation gets some nice extra details from Instruments. Here is an example result for an old iPhone 5:
// map[hwCPU64BitCapable:1 hwCPUsubtype:1 hwCPUtype:16777228 numberOfCpus:2 numberOfPhysicalCpus:2 speedOfCpus:0]
func (d DeviceInfoService) HardwareInformation() (map[string]interface{}, error) {
response, err := d.channel.MethodCall("hardwareInformation")
if err != nil {
return map[string]interface{}{}, err
}
return extractMapPayload(response)
}

// NetworkInformation gets a list of all network interfaces for the device. Example result:
// map[en0:Wi-Fi en1:Ethernet Adaptor (en1) en2:Ethernet Adaptor (en2) lo0:Loopback pdp_ip0:Cellular (pdp_ip0)
// pdp_ip1:Cellular (pdp_ip1) pdp_ip2:Cellular (pdp_ip2) pdp_ip3:Cellular (pdp_ip3) pdp_ip4:Cellular (pdp_ip4)]
func (d DeviceInfoService) NetworkInformation() (map[string]interface{}, error) {
response, err := d.channel.MethodCall("networkInformation")
if err != nil {
return map[string]interface{}{}, err
}
return extractMapPayload(response)
}

func mapToProcInfo(procList []interface{}) []ProcessInfo {
result := make([]ProcessInfo, len(procList))
for i, procMapInt := range procList {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"github.com/danielpaulus/go-ios/ios"
dtx "github.com/danielpaulus/go-ios/ios/dtx_codec"
"github.com/danielpaulus/go-ios/ios/nskeyedarchiver"
log "github.com/sirupsen/logrus"
"io"
"time"
Expand All @@ -15,40 +14,6 @@ type channelDispatcher struct {
closeChannel chan struct{}
}

func toMap(msg dtx.Message) (string, map[string]interface{}, error) {
if len(msg.Payload) != 1 {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v has payload size !=1", msg)
}
selector, ok := msg.Payload[0].(string)
if !ok {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v payload: %+v wasn't a string", msg, msg.Payload[0])
}
args := msg.Auxiliary.GetArguments()
if len(args) == 0 {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v has an empty auxiliary dictionary", msg)
}

data, ok := args[0].([]byte)
if !ok {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v invalid aux", msg)
}

unarchived, err := nskeyedarchiver.Unarchive(data)
if err != nil {
return "", map[string]interface{}{}, err
}
if len(unarchived) == 0 {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v invalid aux", msg)
}

aux, ok := unarchived[0].(map[string]interface{})
if !ok {
return "", map[string]interface{}{}, fmt.Errorf("error extracting, msg %+v auxiliary: %+v didn't contain a map[string]interface{}", msg, msg.Payload[0])
}

return selector, aux, nil
}

func ListenAppStateNotifications(device ios.DeviceEntry) (func() (map[string]interface{}, error), func() error, error) {
conn, err := connectInstruments(device)
if err != nil {
Expand Down
35 changes: 26 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,16 +343,14 @@ The commands work as following:
}
b, _ = arguments.Bool("toggle")
if b {
assistiveTouch(device, "toggle" , force)
assistiveTouch(device, "toggle", force)
}
b, _ = arguments.Bool("get")
if b {
assistiveTouch(device, "get", force)
}
}



b, _ = arguments.Bool("dproxy")
if b {
log.SetFormatter(&log.TextFormatter{})
Expand Down Expand Up @@ -960,10 +958,10 @@ func assistiveTouch(device ios.DeviceEntry, operation string, force bool) {

wasEnabled, err := ios.GetAssistiveTouch(device)

if err != nil{
if force && ( operation == "enable" || operation == "disable" ) {
if err != nil {
if force && (operation == "enable" || operation == "disable") {
log.WithFields(log.Fields{"error": err}).Warn("Failed getting current AssistiveTouch status. Continuing anyway.")
} else{
} else {
exitIfError("failed getting current AssistiveTouch status", err)
}
}
Expand All @@ -973,20 +971,20 @@ func assistiveTouch(device ios.DeviceEntry, operation string, force bool) {
enable = true
case operation == "disable":
enable = false
case operation == "toggle":
case operation == "toggle":
enable = !wasEnabled
default: // get
enable = wasEnabled
}
if operation != "get" && ( force || wasEnabled != enable ) {
if operation != "get" && (force || wasEnabled != enable) {
err = ios.SetAssistiveTouch(device, enable)
exitIfError("failed setting AssistiveTouch", err)
}
if operation == "get" {
if JSONdisabled {
fmt.Printf("%t\n", enable)
} else {
fmt.Println(convertToJSONString(map[string]bool{"AssistiveTouchEnabled":enable}))
fmt.Println(convertToJSONString(map[string]bool{"AssistiveTouchEnabled": enable}))
}
}
}
Expand Down Expand Up @@ -1353,6 +1351,25 @@ func printDeviceInfo(device ios.DeviceEntry) {
if err != nil {
exitIfError("failed getting info", err)
}
svc, err := instruments.NewDeviceInfoService(device)
if err != nil {
log.Debugf("could not open instruments, probably dev image not mounted %v", err)
}
if err == nil {
info, err := svc.NetworkInformation()
if err != nil {
log.Debugf("error getting networkinfo from instruments %v", err)
} else {
allValues["instruments:networkInformation"] = info
}
info, err = svc.HardwareInformation()
if err != nil {
log.Debugf("error getting hardwareinfo from instruments %v", err)
} else {
allValues["instruments:hardwareInformation"] = info
}
}

fmt.Println(convertToJSONString(allValues))
}

Expand Down

0 comments on commit 904b5af

Please sign in to comment.