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
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "bkg.png",
"idiom" : "tv"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "logo.png",
"idiom" : "tv"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "mask_clean.png",
"idiom" : "tv"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"images" : [
{
"filename" : "bkg@1x.png",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "bkg@2x.png",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"layers" : [
{
"filename" : "Front.imagestacklayer"
},
{
"filename" : "Middle.imagestacklayer"
},
{
"filename" : "Back.imagestacklayer"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"images" : [
{
"filename" : "logo@1x.png",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "logo@2x.png",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"images" : [
{
"filename" : "mask_clean@1x.png",
"idiom" : "tv",
"scale" : "1x"
},
{
"filename" : "mask_clean@2x.png",
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"assets" : [
{
"filename" : "App Icon - App Store.imagestack",
"idiom" : "tv",
"role" : "primary-app-icon",
"size" : "1280x768"
},
{
"filename" : "App Icon.imagestack",
"idiom" : "tv",
"role" : "primary-app-icon",
"size" : "400x240"
},
{
"filename" : "Top Shelf Image Wide.imageset",
"idiom" : "tv",
"role" : "top-shelf-image-wide",
"size" : "2320x720"
},
{
"filename" : "Top Shelf Image.imageset",
"idiom" : "tv",
"role" : "top-shelf-image",
"size" : "1920x720"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
},
{
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"images" : [
{
"idiom" : "tv",
"scale" : "1x"
},
{
"idiom" : "tv",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
8 changes: 8 additions & 0 deletions DeviceKitTests/JSONRPC/Handlers/DeviceInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@ struct DeviceInfoMethodHandler: RPCMethodHandler {

let start = Date()

#if os(tvOS)
// tvOS has no SpringBoard; the main screen bounds describe the full UI.
let bounds = UIScreen.main.bounds
let scale = Int(UIScreen.main.scale)
let width = Int(bounds.width)
let height = Int(bounds.height)
#else
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let frame = springboard.frame
let scale = Int(UIScreen.main.scale)
let width = Int(frame.width)
let height = Int(frame.height)
#endif

let duration = Date().timeIntervalSince(start)
logger.info("Device info took \(duration), screen: \(width)x\(height)@\(scale)x")
Expand Down
12 changes: 12 additions & 0 deletions DeviceKitTests/JSONRPC/Handlers/DumpUI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,15 @@ struct DumpUIMethodHandler: RPCMethodHandler {
do {
let foregroundApp = RunningApp.getForegroundApp()
guard let foregroundApp = foregroundApp else {
#if os(iOS)
logger.warning("No foreground app found, returning springboard app hierarchy")
let springboardHierarchy = try elementHierarchy(xcuiElement: springboardApplication)
return try formatResponse(axElement: springboardHierarchy, format: format)
#else
// tvOS has no SpringBoard; without a foreground app there is no
// hierarchy to serialise.
throw RPCMethodError.internalError("No foreground app found")
#endif
}

logger.info("[Start] View hierarchy snapshot for \(foregroundApp)")
Expand Down Expand Up @@ -106,6 +112,7 @@ struct DumpUIMethodHandler: RPCMethodHandler {
SystemPermissionManager.handleSystemPermissionAlertIfNeeded(foregroundApp: foregroundApp)
let appHierarchy = try getHierarchyWithFallback(foregroundApp)

#if os(iOS)
let statusBars = logger.measure(message: "Fetch status bar hierarchy") {
fullStatusBars(springboardApplication)
} ?? []
Expand Down Expand Up @@ -134,6 +141,11 @@ struct DumpUIMethodHandler: RPCMethodHandler {
}

return buildRootElement(app: appHierarchy, statusBars: statusBars, safari: safariWebViewHierarchy)
#else
// tvOS has no SpringBoard / status bars / Safari view service. Use the
// foreground app's own root hierarchy directly.
return buildRootElement(app: appHierarchy, statusBars: [], safari: nil)
#endif
}

private func buildRootElement(app: AXElement, statusBars: [AXElement], safari: AXElement?) -> AXElement {
Expand Down
68 changes: 67 additions & 1 deletion DeviceKitTests/JSONRPC/Handlers/IOButton.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import XCTest
import os

struct IOButtonRequest : Codable {
#if os(iOS)

struct IOButtonRequest: Codable {
enum Button: String, Codable {
case home
case lock
Expand Down Expand Up @@ -52,3 +55,66 @@ struct IOButtonMethodHandler: RPCMethodHandler {
}
}

#elseif os(tvOS)

struct IOButtonRequest: Codable {
/// tvOS is driven by the Siri Remote. Every button maps to an
/// `XCUIRemote.Button` press against the currently focused element.
enum Button: String, Codable {
case up
case down
case left
case right
case select
case menu
case home
case playPause
}

let button: Button
}

@MainActor
struct IOButtonMethodHandler: RPCMethodHandler {
static let methodName = "device.io.button"

private let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: Self.self)
)

func execute(params: JSONValue?) async throws -> JSONValue {
let request = try decodeParams(IOButtonRequest.self, from: params)

let start = Date()

logger.info("[Start] Pressing remote button: \(request.button.rawValue)")
let remoteButton: XCUIRemote.Button
switch request.button {
case .up:
remoteButton = .up
case .down:
remoteButton = .down
case .left:
remoteButton = .left
case .right:
remoteButton = .right
case .select:
remoteButton = .select
case .menu:
remoteButton = .menu
case .home:
remoteButton = .home
case .playPause:
remoteButton = .playPause
}
XCUIRemote.shared.press(remoteButton)
logger.info("[Done] Pressing remote button: \(request.button.rawValue)")

let duration = Date().timeIntervalSince(start)
logger.info("Remote button press duration took \(duration)")
return .object(["success": .bool(true)])
}
}

#endif
Loading