Using Settings

Settings is part of the Fuchsia SDK and is available on products with the proper supporting packages. Applications on these products can interact with Settings if they have the appropriate permissions. The interaction follows a common pattern for accessing and modifying settings across the Settings protocols.

This guide walks through the steps for incorporating Settings into an application and interacting with Settings.

Prerequisites

The Setting Service supports the Settings protocols in Fuchsia. The service's package /garnet/bin/setui:setui_service must be present in the product definition in order to use Settings. The following product definition includes Settings:

import("//products/bringup.gni")

base_package_labels += [
  "//garnet/bin/setui:setui_service",
]

The service is associated with Settings through sysmgr, which maps the protocols to the service. Since the service‘s dependencies are downstream from other system components, Settings is an optional and need not be included on products that don’t utilize it.

For more information about Fuchsia's build system, see The Fuchsia build system.

Permissions

Any application that accesses Settings must declare usage through its component manifest. The application is granted access to the protocols listed under services in the sandbox section. For example, the following manifest declares access to the fuchsia.settings.accessibility:

{
    "program": {
        "binary": "bin/example"
    },
    "sandbox": {
        "services": [
            "fuchsia.settings.Accessibility",
        ]
    }
}

For more information about Fuchsia components, see Component manifests (Components v1).

Connecting

Applications access Settings through the runtime bindings found in the Fuchsia SDK. This guide will use Rust for examples, but bindings are available for a variety of other languages, such as C++ and Dart.

Like other FIDL protocols, the first step to accessing Settings is to connect to the Setting Service. The following example connects to fuchsia.settings.accessibility:

let proxy = connect_to_service::<AccessibilityMarker>().context(“failed to connect to Settings”);

In the above example, connect_to_service and AccessibilityMarker are provided through the SDK.

Clients should communicate with each Setting protocol over a single connection. Ongoing communication must occur over the same connection to ensure the consistency and continuity of responses, as explored in later sections.

Reading

Each Setting protocol defines a table for conveying relevant details, such as state and status. Organizing data under a single structure allows Settings to succinctly convey information. The structure also facilitates communicating changes, as discussed later. In the Accessibility example, AccessibilitySettings captures relevant details:

/// Supported accessibility settings.
table AccessibilitySettings {
    /// For videos, use an alternative audio track (akin to changing languages)
    /// that explains what is happening visually while there is no dialogue.
    1: bool audio_description;

    /// Read aloud elements of the screen selected by the user.
    2: bool screen_reader;

    /// Invert colors on the screen.
    3: bool color_inversion;

    /// Interpret triple-tap on the touchscreen as a command to zoom in.
    4: bool enable_magnification;

    /// What type of color-blindness, if any, to correct for.
    5: ColorBlindnessType color_correction;

    /// What kind of sources get closed captions, and how they look.
    6: CaptionsSettings captions_settings;
};

A method, called Watch, is present in each protocol to provide access to this information. This is the declaration for fuchsia.settings.accessibility:

Watch() -> (AccessibilitySettings settings);

Watch follows the hanging get pattern, returning the current information on the initial call. Responses to subsequent invocations are deferred until there is an update to the last returned value. Using the same proxy connection across these requests is critical for this behavior as Settings tracks the delivered responses based on the channel. If an error occurs, Settings will close the FIDL channel with a relevant epitaph.

In the Accessibility example, call Watch to determine if the screen reader is enabled:

let settings = proxy.watch().expect(“settings retrieved”);
let screen_reader_enabled = settings.screen_reader.ok_or(false);

Writing

Applications can affect Settings by utilizing the same table structure found for reading data. Each mutable protocol offers a counterpart method to Watch called Set, which takes AccessibilitySettings as an argument:

Set(AccessibilitySettings settings) -> () error Error;

Changes are conveyed by specifying the desired final state in the table fields. Since each field is optional, only affected fields need to be specified. By defining changes as deltas, race conditions from multiple callers are avoided. If successful, the change will be persisted and applied across boots. Continuing the previous example, a caller can enable the screen reader with the following code:

let new_settings = AccessibilitySettings::EMPTY;
new_settings.screen_reader = Some(true);
proxy.set(new_settings).await.expect(“request completed”).expect(“request succeeded”);

Debugging

Settings offers a command-line utility for interacting with its protocols, called SetUI Client. This tool gives developers real-time access to Settings, enabling them to see how their application affects and is affected by Settings. SetUI Client can be included in a build by specifying its package in the build environment:

fx set core.x64 --with //garnet/packages/prod:setui_client

Since the utility is not part of the base packages, it is important to have the package server serving at execution time. A Setting protocol‘s current information can be retrieved by calling SetUI client with the protocol’s name as an argument. For example, the following command retrieves information about Accessibility:

fx shell run fuchsia-pkg://fuchsia.com/setui_client#meta/setui_client.cmx accessibility

SetUI Client can also modify Settings. The utility's help command details the specific modification syntax per protocol:

fx shell run fuchsia-pkg://fuchsia.com/setui_client#meta/setui_client.cmx accessibility help

Finishing the example, the SetUI Client can be done as follows:

fx shell run fuchsia-pkg://fuchsia.com/setui_client#meta/setui_client.cmx accessibility -s true