android

package
v2.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2026 License: GPL-3.0 Imports: 39 Imported by: 0

Documentation

Overview

Package android is the Android platform. It is ordinary Go: everything that needs the Android framework goes through the Host the embedding host supplies.

Index

Constants

View Source
const (

	// StrategyFilesystemPath hands the target a transient filesystem path.
	StrategyFilesystemPath = "filesystem_path"
	// StrategyContentURI hands the target a content URI with a read grant.
	StrategyContentURI = "content_uri"
	// StrategyApp starts an installed app with no media at all. The optional
	// literal extras select one profile-defined variant of it.
	StrategyApp = "app"
)

Variables

View Source
var ErrAppIdentity = errors.New("invalid android app identity")

ErrAppIdentity is returned for a virtual path that is not a launchable Android app identity.

View Source
var ErrLaunchDefinition = errors.New("invalid or unsupported launch definition")

ErrLaunchDefinition reports a launch definition that is malformed or asks for a capability this platform does not support.

Functions

This section is empty.

Types

type AppIdentity

type AppIdentity struct {
	Package string
	Variant string
	Name    string
}

AppIdentity is an installed app, optionally one profile-defined variant of it. It is identity only: the activity, action and extras that actually start the app live in the catalog, so an app that renames an activity does not invalidate identities already written to a card.

func ParseAppPath

func ParseAppPath(path string) (AppIdentity, error)

ParseAppPath reads an "android://" virtual path back into an identity.

func (AppIdentity) AppPath

func (a AppIdentity) AppPath() string

AppPath renders the identity as "android://<package>[:<variant>]/<Name>".

type AppInfo

type AppInfo struct {
	Package  string
	Activity string
	Label    string
}

AppInfo is one launchable app the host found. Label is the app's own display name, which the host reads from the platform, never Core.

type DispatchReceipt

type DispatchReceipt struct {
	Package  string
	Activity string
	Strategy string
}

DispatchReceipt names the component the host actually started, so the platform can confirm it is the one the definition asked for.

type FailureReason

type FailureReason string

FailureReason is a stable code for why the host could not inspect or start a launch target. It carries no user-facing text.

const (
	// FailureHostUnavailable means the host could not be reached at all.
	FailureHostUnavailable FailureReason = "host-unavailable"
	// FailureInvalidResponse means the host answered with something malformed.
	FailureInvalidResponse FailureReason = "invalid-response"
	// FailureNotInstalled means the target package is not installed.
	FailureNotInstalled FailureReason = "not-installed"
	// FailureActivityUnavailable means the package lacks a launchable target activity.
	FailureActivityUnavailable FailureReason = "activity-unavailable"
	// FailureStorageDenied means the target app has no storage permission.
	FailureStorageDenied FailureReason = "storage-denied"
	// FailureStorageVersion means the target build's storage access cannot be verified.
	FailureStorageVersion FailureReason = "storage-version"
	// FailureProviderUnsupported means the document provider cannot yield a local file.
	FailureProviderUnsupported FailureReason = "provider-unsupported"
	// FailureStorageUnmounted means the volume holding the media is not mounted.
	FailureStorageUnmounted FailureReason = "storage-unmounted"
	// FailureSourceUnavailable means the media file cannot be reached in its media folder.
	FailureSourceUnavailable FailureReason = "source-unavailable"
	// FailureSourceRevoked means the host's own access to the media's source
	// folder was revoked or withdrawn, distinct from FailureSourceUnavailable's
	// unspecified cause: the user can act on this one by re-granting access.
	FailureSourceRevoked FailureReason = "source-revoked"
	// FailureForegroundRequired means the host UI must be in front to start an activity.
	FailureForegroundRequired FailureReason = "foreground-required"
	// FailureCancelled means the dispatch was cancelled before it started.
	FailureCancelled FailureReason = "cancelled"
	// FailureOutcomeUnknown means the host cannot tell whether the target started.
	FailureOutcomeUnknown FailureReason = "outcome-unknown"
	// FailureRefused covers every other refusal.
	FailureRefused FailureReason = "refused"
)

type ForegroundState

type ForegroundState struct {
	BootID      string
	Permission  string
	SampledMs   int64
	ElapsedMs   int64
	Version     int
	Interactive bool
	Unlocked    bool
}

ForegroundState is a host-owned snapshot taken before intent dispatch or a reconciliation pass. It also supplies the boot and elapsed clocks needed to reject cross-boot replay.

type Host

type Host interface {
	// InspectTarget reports whether the definition's package and activity are
	// installed and launchable. A nil error means they are; a *HostError says
	// why not.
	InspectTarget(definition *LaunchDefinition) error
	// InstalledCores lists the launcher core files the host found. scanned is
	// false when the host has not looked, which is not evidence of absence.
	InstalledCores() (files []string, scanned bool)
	// MediaFolders returns the references of the media folders Core may
	// index now. A folder whose grant was revoked is not listed.
	MediaFolders(ctx context.Context) ([]string, error)
	// ReadMediaDir lists the directory at segments below the folder named by
	// reference; no segments lists the folder itself.
	ReadMediaDir(ctx context.Context, reference string, segments []string) ([]platforms.SourceEntry, error)
	// ReadFile returns up to limit+1 bytes of the file at segments below the
	// folder named by reference, so an oversized file is detectable. It is
	// used only at launch, to read the small amount of a media file's own
	// content a launch needs; indexing never reads a file's content.
	ReadFile(ctx context.Context, reference string, segments []string, limit int64) ([]byte, error)
	// Dispatch starts a validated definition for the file at segments below
	// the folder named by reference. Cancelling ctx abandons a dispatch in
	// flight. A *HostError says why the host refused.
	Dispatch(
		ctx context.Context,
		definition *LaunchDefinition,
		reference string,
		segments []string,
	) (DispatchReceipt, error)
	// InstalledApps lists the launchable apps the host found. scanned is false
	// when the host has not looked, which is not evidence of absence.
	InstalledApps() (apps []AppInfo, scanned bool)
	// AppIcon returns a readable, app-private PNG for a launchable package.
	// An unavailable icon is not evidence that the app is absent.
	AppIcon(packageName string) (path string, err error)
	// DispatchApp starts a definition that carries no media. A *HostError says
	// why the host refused.
	DispatchApp(definition *LaunchDefinition) (DispatchReceipt, error)
	// ForegroundState reads a fresh framework snapshot: boot identity, Usage
	// Access permission, and screen/keyguard state, on both the wall and
	// elapsed clocks. It is read fresh before every dispatch and
	// reconciliation pass; the platform never caches it.
	ForegroundState() (ForegroundState, error)
	// ForegroundEvents queries a bounded window of privacy-filtered
	// foreground evidence for one already-dispatched launch's whole
	// package - never a specific activity, so an intent that forwards
	// through more than one activity of the same app still reads as one
	// session. Cancelling ctx abandons a query in flight.
	ForegroundEvents(
		ctx context.Context, launchID, target string, fromMs, toMs int64,
	) (database.ForegroundEvidence, error)
}

Host is the embedding host's authority over the Android framework. The platform never touches packages, intents or document providers itself. Implementations must be safe for concurrent use.

Media folders the user granted to the host are named by the host's own reference for each, which Core treats as opaque. Core turns references into source roots and never shows or stores one.

type HostError

type HostError struct {
	Reason FailureReason
}

HostError is the typed failure a Host returns. Any other error from a Host is treated as FailureHostUnavailable.

func (*HostError) Error

func (e *HostError) Error() string

type HostReturn

type HostReturn struct {
	// ObserverStartedElapsedMs is when the UI process now reporting started.
	// A launch dispatched before it came from a process that died, so no
	// return can ever be observed for it. Zero when unknown.
	ObserverStartedElapsedMs int64
	// ReturnedWallMs and ReturnedElapsedMs are the earliest launcher resume
	// the host has not yet delivered. Zero when there was none.
	ReturnedWallMs    int64
	ReturnedElapsedMs int64
}

HostReturn is what the host observed of its own launcher UI, all from one boot: the UI process cannot outlive a reboot.

type LaunchDefinition

type LaunchDefinition struct {
	ID            string `json:"id"`
	Name          string `json:"name,omitempty"`
	Variant       string `json:"variant,omitempty"`
	System        string `json:"system"`
	Package       string `json:"package"`
	Activity      string `json:"activity"`
	Action        string `json:"action"`
	Strategy      string `json:"strategy"`
	StorageAccess string `json:"storageAccess"`
	Repair        string `json:"repair"`
	DataSource    string `json:"dataSource,omitempty"`
	// Data is an Intent data URI, set only at dispatch from a file the
	// definition itself carries no reference to. Reserved for the one
	// package whose exported activity reads its target from Intent data
	// (scummVMPackage); every other definition must leave it empty.
	Data         string        `json:"data,omitempty"`
	Extensions   []string      `json:"extensions"`
	Extras       []LaunchExtra `json:"extras,omitempty"`
	Version      int           `json:"version"`
	MaxTargetSDK int           `json:"maxTargetSdk,omitempty"`
	GrantReadURI bool          `json:"grantReadUri,omitempty"`
	ClipData     bool          `json:"clipData,omitempty"`
}

LaunchDefinition is binding data: which component to start and how media reaches it. Version 1 carries a transient filesystem path. Version 2 carries a content URI with an explicit read grant and ClipData. A host must never silently substitute one strategy for the other.

func (*LaunchDefinition) Validate

func (d *LaunchDefinition) Validate() error

Validate reports ErrLaunchDefinition unless every field is bounded and the definition uses exactly one supported strategy.

type LaunchExtra

type LaunchExtra struct {
	Name   string `json:"name"`
	Type   string `json:"type"`
	Source string `json:"source"`
	Suffix string `json:"suffix,omitempty"`
	Value  string `json:"value,omitempty"`
}

LaunchExtra binds one typed intent extra to a host capability, not a string template. Extras are string unless a package's own intent contract needs otherwise; adding a type for general use requires host negotiation.

type Platform

type Platform struct {
	// contains filtered or unexported fields
}

Platform implements platforms.Platform for Android. Token readers, input and screenshots have no host capability yet and report ErrNotSupported.

func New

func New(settings platforms.Settings, host Host) (*Platform, error)

New builds the platform over the directories the host owns. A nil host yields a platform with no launchers and no media.

func (*Platform) ConsoleManager

func (*Platform) ConsoleManager() platforms.ConsoleManager

func (*Platform) ForwardCmd

func (*Platform) ForwardCmd(*platforms.CmdEnv) (platforms.CmdResult, error)

func (*Platform) GamepadPress

func (*Platform) GamepadPress(string) error

func (*Platform) ID

func (*Platform) ID() string

func (*Platform) InvalidateHostSnapshot

func (p *Platform) InvalidateHostSnapshot()

InvalidateHostSnapshot drops the memoised host report so the next launcher listing or launch asks the host again. An embedding host calls it when packages are installed, removed or changed, and when the RetroArch core list changes.

func (*Platform) KeyboardPress

func (*Platform) KeyboardPress(string) error

func (*Platform) LaunchMedia

func (p *Platform) LaunchMedia(
	cfg *config.Instance,
	path string,
	launcher *platforms.Launcher,
	db *database.Database,
	options *platforms.LaunchOptions,
) error

LaunchMedia starts path with launcher, or with the launcher Core's usual inference picks when none was chosen upstream.

func (*Platform) LaunchSystem

func (*Platform) LaunchSystem(*config.Instance, string) error

func (*Platform) Launchers

func (p *Platform) Launchers(*config.Instance) []platforms.Launcher

Launchers lists the catalog in precedence order: within a system, the first launcher is the preferred one.

func (*Platform) LookupMapping

func (*Platform) LookupMapping(*tokens.Token) (string, bool)

func (*Platform) ManagedByPackageManager

func (*Platform) ManagedByPackageManager() bool

ManagedByPackageManager is true: the host's package is the only update path.

func (*Platform) ReadSourceDir

func (p *Platform) ReadSourceDir(ctx context.Context, path string) ([]platforms.SourceEntry, error)

ReadSourceDir lists a directory in one of the host's media folders.

func (*Platform) ReadSourceFile

func (p *Platform) ReadSourceFile(ctx context.Context, path string, limit int64) ([]byte, error)

ReadSourceFile returns up to limit+1 bytes of the file at path, so an oversized file is detectable. Unlike SourceRoots/ReadSourceDir, this is not part of platforms.SourceRootReader (indexing never calls it) - it satisfies the separate platforms.SourceFileReader capability instead, used at launch time by ScummVM/GameNative and to serve a scraped folder cover's bytes.

func (*Platform) ReconcileExternalSessions

func (p *Platform) ReconcileExternalSessions(ctx context.Context) error

ReconcileExternalSessions queries only recorded launch targets. The persisted cursor and store transaction make repeated host observations idempotent. It is run at startup and after every host return.

func (*Platform) ReconcileSessions

func (p *Platform) ReconcileSessions(ctx context.Context, observed HostReturn) error

ReconcileSessions runs after the frontend returns: it closes approximate launches from the observed return, then queries foreground evidence once it has settled.

func (*Platform) RefreshLauncherDependencies

func (p *Platform) RefreshLauncherDependencies() error

RefreshLauncherDependencies drops the memoised host report, so an explicit launchers.refresh sees a RetroArch core install without waiting out hostSnapshotTTL.

func (*Platform) ReturnToMenu

func (*Platform) ReturnToMenu() error

func (*Platform) RootDirs

func (*Platform) RootDirs(*config.Instance) []string

RootDirs is empty: media comes from the host's media folders, which Core indexes as source roots.

func (*Platform) ScanHook

func (*Platform) ScanHook(*tokens.Token) error

func (*Platform) Scrapers

func (p *Platform) Scrapers(*config.Instance) map[string]platforms.Scraper

Scrapers offers the libretro thumbnail scraper (box art, screenshots and title screens for indexed media, matched by libretro's own sanitised name; it never runs automatically after indexing, since it is the only scraper that downloads) and, once a host is present, an app icon scraper for installed apps offered as media.

func (*Platform) Screenshot

func (*Platform) Screenshot() (*platforms.ScreenshotResult, error)

func (*Platform) SetMediaHistoryHooks

func (p *Platform) SetMediaHistoryHooks(hooks platforms.MediaHistoryHooks)

SetMediaHistoryHooks receives the service's profile and history notification hooks. Android history for a LifecycleExternal launcher comes from session reconciliation, not the active-media tracker.

func (*Platform) SetTrackedProcess

func (*Platform) SetTrackedProcess(*os.Process)

func (*Platform) Settings

func (p *Platform) Settings() platforms.Settings

func (*Platform) SourceRoots

func (p *Platform) SourceRoots(ctx context.Context) ([]string, error)

SourceRoots lists the media folders the user granted to the host.

func (*Platform) StartPost

func (p *Platform) StartPost(
	ctx context.Context,
	_ *config.Instance,
	launcherContexts platforms.LauncherContextManager,
	_ func() *models.ActiveMedia,
	_ func(*models.ActiveMedia),
	db *database.Database,
	_ *idle.Scheduler,
) error

func (*Platform) StartPre

func (*Platform) StartPre(*config.Instance) error

func (*Platform) Stop

func (p *Platform) Stop() error

Stop drops the launcher contexts StartPost supplied. A host reuses one Platform across starts, and the manager from the previous run holds a cancelled context: leaving it in place makes launcherContext's readiness check pass with a dead context instead of refusing the launch.

func (*Platform) StopActiveLauncher

func (*Platform) StopActiveLauncher(platforms.StopIntent) error

func (*Platform) SupportedReaders

func (*Platform) SupportedReaders(*config.Instance) []readers.Reader

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL