Skip to content

Running dev on device Iphone 15+ and IOS17+ will fail if you have a Apple Watch in Run Destinations. #417

@iskng

Description

@iskng

Describe the bug
devicectl::parse_device_list() is deserializing assuming "cpuType" on all devices but devicectl doesn't output one for apple watch.

Causes:
thread 'apple::device::devicectl::device_list::tests::test_parse_device_list' panicked at src/apple/device/devicectl/device_list.rs:405:47:
Failed to parse device list: InvalidDeviceList(Error("missing field cpuType", line: 261, column: 9))

Steps To Reproduce
Steps to reproduce the behavior. It must use cargo-mobile2 itself and wry template directly instead of tauri-cli.
Have an apple watch paired to xcode and an iphone 15+ with ios 17+
pnpm tauri dev --host (yep read the above)

Add this test to src/apple/device/devicectl/device_list.rs
Its a slimmed down version of my devicectl output.

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_device_list() {
        let json =
            r#"{
  "info" : {
    "arguments" : [
      "devicectl",
      "list",
      "devices",
      "--json-output",
      "/Users/arst/arst/arst/arst/arst/devicelist.json"
    ],
    "commandType" : "devicectl.list.devices",
    "environment" : {
      "TERM" : "xterm-256color"
    },
    "jsonVersion" : 2,
    "outcome" : "success",
    "version" : "355.28"
  },
  "result" : {
    "devices" : [
      {
        "capabilities" : [
          {
            "featureIdentifier" : "Cryptex1",
            "name" : "com.apple.security.cryptexd.remote"
          },
          {
            "featureIdentifier" : "com.apple.coredevice.feature.getdeviceinfo",
            "name" : "Fetch Extended Device Info"
          }
        ],
        "connectionProperties" : {
          "authenticationType" : "manualPairing",
          "isMobileDeviceOnly" : false,
          "lastConnectionDate" : "2024-10-26T04:57:34.972Z",
          "localHostnames" : [
            "PhoneName.coredevice.local",
            "arstasrt-arstasrtastasrt.coredevice.local",
            "arstarstas-arst-arst-arst-arstasrtasrt.coredevice.local"
          ],
          "pairingState" : "paired",
          "potentialHostnames" : [
            "arstarst-arstasrtasrtarstas.coredevice.local",
            "arstarst-arst-arst-arst-arstarstasrt.coredevice.local"
          ],
          "transportType" : "wired",
          "tunnelIPAddress" : "fda8:33d4:a882::1",
          "tunnelState" : "connected",
          "tunnelTransportProtocol" : "tcp"
        },
        "deviceProperties" : {
          "bootedFromSnapshot" : true,
          "bootedSnapshotName" : "com.apple.os.update-arstarstarstarstarstarstarstarstarstarstarstasrtarstasrars",
          "bootState" : "booted",
          "ddiServicesAvailable" : true,
          "developerModeStatus" : "enabled",
          "hasInternalOSBuild" : false,
          "name" : "Fown",
          "osBuildUpdate" : "21G93",
          "osVersionNumber" : "17.6.1",
          "rootFileSystemIsWritable" : false,
          "screenViewingURL" : "coredevice-devices:/viewDeviceByUUID?uuid=arstarst-arst-arst-arst-arstarstarst"
        },
        "hardwareProperties" : {
          "cpuType" : {
            "name" : "arm64",
            "subType" : 2,
            "type" : 16777228
          },
          "deviceType" : "iPhone",
          "ecid" : 123412341324123,
          "hardwareModel" : "D83AP",
          "internalStorageCapacity" : 1024000000000,
          "isProductionFused" : true,
          "marketingName" : "iPhone 15 Pro",
          "platform" : "iOS",
          "productType" : "iPhone16,1",
          "reality" : "physical",
          "serialNumber" : "arstarstars",
          "supportedCPUTypes" : [
            {
              "name" : "arm64e",
              "subType" : 2,
              "type" : 16777228
            },
            {
              "name" : "arm64",
              "subType" : 0,
              "type" : 16777228
            },
            {
              "name" : "arm64",
              "subType" : 1,
              "type" : 16777228
            },
            {
              "name" : "arm64_32",
              "subType" : 1,
              "type" : 33554444
            }
          ],
          "supportedDeviceFamilies" : [
            1
          ],
          "thinningProductType" : "iPhone16,1",
          "udid" : "arstarsta-arstasrtarstas"
        },
        "identifier" : "arstarsta-arsa-arsta-arst-arstarstarst",
        "visibilityClass" : "default"
      },
      {
        "capabilities" : [
          {
            "featureIdentifier" : "com.apple.coredevice.feature.unpairdevice",
            "name" : "Unpair Device"
          }
        ],
        "connectionProperties" : {
          "authenticationType" : "manualPairing",
          "isMobileDeviceOnly" : false,
          "pairingState" : "paired",
          "potentialHostnames" : [
            "arstarstar-starstasrtasrt.coredevice.local",
            "arstarstasrtars-tarstasrtastasrt.coredevice.local"
          ],
          "tunnelState" : "unavailable"
        },
        "deviceProperties" : {
          "ddiServicesAvailable" : false,
          "name" : "Frank’s Apple Watch"
        },
        "hardwareProperties" : {
          "deviceType" : "appleWatch",
          "ecid" : 1234132411234,
          "platform" : "watchOS",
          "productType" : "Watch7,5",
          "udid" : "arstarstarst"
        },
        "identifier" : "arstarstast-arstarstarst-arstarst",
        "visibilityClass" : "default"
      }
    ]
  }
}
"#.to_string();

        let devices = parse_device_list(json).expect("Failed to parse device list");

        // Should only get one device since the other has tunnelState: "unavailable"
        assert_eq!(devices.len(), 1, "Expected exactly one device");

        let device = devices.iter().next().unwrap();
        assert_eq!(device.name(), "Fown");
        assert_eq!(device.model(), "iPhone16,1");
        assert_eq!(device.kind(), DeviceKind::DeviceCtlDevice);
    }
}

Expected behavior
Should be able to parse the list regardless of other devices in the Run Destinations
lazy fix is unpair watch or filter_map an Option but haven't checked if an apple tv or other platforms are different

Platform and Versions (please complete the following information):
Host OS: Mac 14.5
Target OS: IOS 17.6.1
Rustc: 1.82

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions