chromium/chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// API and definitions exposed by the Telemetry Routine Services. This API is
// normally consumed by the Telemetry Extension APIs implementation.

// Note: this is a subset of the cros_healthd routine service interface which is
// located in
// //chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_routines.mojom
// This interface serves as PII filtering and data post-processing service
// between the source (cros_healthd) and the clients
// (third-party telemetry extensions).
//
// This interface is in the process of being synced to Chromium from ChromiumOS.
// Thus, we have the following routines that are supported by cros_healthd in
// ChromiumOS but not yet part of this crosapi interface (in both
// `TelemetryDiagnosticRoutineArgument` and `TelemetryDiagnosticRoutineDetail`):
// - Audio driver routine
// - Cpu stress routine
// - Ufs lifetime routine
// - Disk read routine
// - Cpu cache routine
// - Prime search routine
// - Battery discharge routine

module crosapi.mojom;

import "chromeos/crosapi/mojom/telemetry_extension_exception.mojom";
import "mojo/public/mojom/base/time.mojom";

// This routine checks whether there is any memory problem by
// reading/writing different patterns.
//
// NextMinVersion: 1, NextIndex: 1
[Stable]
struct TelemetryDiagnosticMemoryRoutineArgument {
  // An optional field to indicate how much memory should be tested. If the
  // value is null, memory test will run with as much memory as possible.
  uint32? max_testing_mem_kib@0;
};

// This routine checks the functionality of the volume button. The routine
// passes if the specified volume button event is received before the timeout.
// Otherwise, the routine fails.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticVolumeButtonRoutineArgument {
  [Stable, Extensible]
  enum ButtonType {
    // The default value is for backward compatibility, should not be used.
    [Default] kUnmappedEnumField = 0,
    kVolumeUp = 1,    // Test for the volume up button.
    kVolumeDown = 2,  // Test for the volume down button.
  };
  // The type of volume button to test.
  ButtonType type@0;
  // Length of time to listen to the volume button events. The timeout should be
  // positive and less or equal to 600 seconds.
  mojo_base.mojom.TimeDelta timeout@1;
};

// This routine checks whether the fan is controllable.
//
// NextMinVersion: 1, NextIndex: 1
[Stable]
struct TelemetryDiagnosticFanRoutineArgument {};

// Enumeration of each possible LED on a device. This enum type is a mirror of
// the enums defined in ChromeOS Embedded Controller (EC). To find out the
// actual name of each installed LED, please refer to the EC firmware.
//
// NextMinVersion: 1, NextIndex: 6
[Stable, Extensible]
enum TelemetryDiagnosticLedName {
  // The default value is for backward compatibility, should not be used.
  [Default] kUnmappedEnumField = 0,
  kBattery = 1,
  kPower = 2,
  kAdapter = 3,
  kLeft = 4,
  kRight = 5,
};

// Enumeration of each possible LED color.
//
// NextMinVersion: 1, NextIndex: 7
[Stable, Extensible]
enum TelemetryDiagnosticLedColor {
  // The default value is for backward compatibility, should not be used.
  [Default] kUnmappedEnumField = 0,
  kRed = 1,
  kGreen = 2,
  kBlue = 3,
  kYellow = 4,
  kWhite = 5,
  kAmber = 6,
};

// The routine lights up the target LED in the specified color and requests the
// caller to verify the change.
//
// This routine is supported if and only if the device has a ChromeOS Embedded
// Controller (EC).
//
// When an LED name or LED color is not supported by the EC, it will cause a
// routine exception (by closing the connection of `RoutineControl`) at runtime.
// TODO(b/319047040): add per-LED-name and per-LED-color supported check.
//
// The routine proceeds with the following steps:
// 1. Set the specified LED with the specified color and enter the waiting state
//    with the `TelemetryDiagnosticCheckLedLitUpStateInquiry` interaction
//    request.
// 2. After receiving `TelemetryDiagnosticCheckLedLitUpStateReply` with the
//    observed LED state, the color of the LED will be reset (back to auto
//    control). Notice that there is no timeout so the routine will be in the
//    waiting state indefinitely.
// 3. The routine passes if `TelemetryDiagnosticCheckLedLitUpStateReply`
//    indicates that the LED lit up in the correct color. Otherwise, the routine
//    fails.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticLedLitUpRoutineArgument {
  // The LED to be lit up.
  TelemetryDiagnosticLedName name@0;
  // The color to be lit up.
  TelemetryDiagnosticLedColor color@1;
};

// This routine checks the network bandwidth and reports the speed info.
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticNetworkBandwidthRoutineArgument {};

// This routine checks the frames captured by camera. The frontend should ensure
// the camera is opened during the execution of the routine.
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticCameraFrameAnalysisRoutineArgument {};

// This routine checks whether the keyboard backlight can be lit up at any
// brightless level.
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticKeyboardBacklightRoutineArgument {};

// Argument types for the possible routines the routine control API can create.
//
// NextMinVersion: 8, NextIndex: 8
[Stable, Extensible]
union TelemetryDiagnosticRoutineArgument {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedArgument @0;
  // Arguments to create a memory routine.
  [MinVersion=1] TelemetryDiagnosticMemoryRoutineArgument memory@1;
  // Arguments to create a volume button routine.
  [MinVersion=2] TelemetryDiagnosticVolumeButtonRoutineArgument volume_button@2;
  // Arguments to create a fan routine.
  [MinVersion=3] TelemetryDiagnosticFanRoutineArgument fan@3;
  // Arguments to create a LED lit up routine.
  [MinVersion=4] TelemetryDiagnosticLedLitUpRoutineArgument led_lit_up@4;
  // Arguments to create a network bandwidth routine.
  [MinVersion=5]
  TelemetryDiagnosticNetworkBandwidthRoutineArgument network_bandwidth@5;
  // Arguments to create a camera framee analysis routine.
  [MinVersion=6]
  TelemetryDiagnosticCameraFrameAnalysisRoutineArgument camera_frame_analysis@6;
  // Arguments to create a keyboard backlight routine.
  [MinVersion=7]
  TelemetryDiagnosticKeyboardBacklightRoutineArgument keyboard_backlight@7;
};

// Routine has been initialized but not yet started.
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticRoutineStateInitialized {};

// Running info regarding network bandwidth routine.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo {
  // The type of test that routine is running.
  //
  // NextMinVersion: 1, NextIndex: 3
  [Stable, Extensible]
  enum Type {
    [Default] kUnmappedEnumField = 0,
    // Routine is running download test.
    kDownload = 1,
    // Routine is running upload test.
    kUpload = 2,
  };
  Type type@0;

  // The current network speed in kbit/s.
  double speed_kbps@1;
};

// Routine running info. Note that not every routine provides info during the
// running state.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
union TelemetryDiagnosticRoutineRunningInfo {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedArgument @0;
  // Running info of network bandwidth routine.
  TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo network_bandwidth@1;
};

// Routine is currently running.
//
// NextMinVersion: 2, NextIndex: 1
[Stable]
struct TelemetryDiagnosticRoutineStateRunning {
  [MinVersion=1] TelemetryDiagnosticRoutineRunningInfo? info@0;
};

// Details to reply to a routine requesting to check the LED lit up state.
//
// NextMinVersion: 1, NextIndex: 1
[Stable]
struct TelemetryDiagnosticCheckLedLitUpStateReply {
  // State of the target LED.
  //
  // NextMinVersion: 1, NextIndex: 3
  [Stable, Extensible]
  enum State {
    // The default value is for backward compatibility, should not be used.
    [Default] kUnmappedEnumField = 0,
    // The LED is lit up with the correct color.
    kCorrectColor = 1,
    // The LED is not lit up with the correct color.
    kNotLitUp = 2
  };
  State state@0;
};

// Details to reply to a routine requesting to check if all the LEDs on the
// keyboard backlight lit up.
//
// NextMinVersion: 1, NextIndex: 1
[Stable]
struct TelemetryDiagnosticCheckKeyboardBacklightStateReply {
  // State of the keyboard backlight LED.
  //
  // NextMinVersion: 1, NextIndex: 3
  [Stable, Extensible]
  enum State {
    // The default value is for backward compatibility, should not be used.
    [Default] kUnmappedEnumField = 0,
    // All keyboard backlight LEDs are lit up.
    kOk = 1,
    // Any of the keyboard backlight LED is not lit up.
    kAnyNotLitUp = 2,
  };
  State state@0;
};

// Details to reply to a routine inquiry.
//
// The following routines are not yet part of this crosapi interface so their
// replies have not been included in this union:
// - Led lit up routine
//
// NextMinVersion: 3, NextIndex: 3
[Stable, Extensible]
union TelemetryDiagnosticRoutineInquiryReply {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedReply@0;
  // Details to resume a routine requesting to check the LED lit up state.
  [MinVersion=1] TelemetryDiagnosticCheckLedLitUpStateReply
      check_led_lit_up_state@1;
  // Details to resume a routine requesting to check the keyboard backlight LED
  // state.
  [MinVersion=2]
  TelemetryDiagnosticCheckKeyboardBacklightStateReply
      check_keyboard_backlight_state@2;
};

// Details regarding the inquiry to check the LED lit up state. Clients should
// inspect the target LED and report its state using
// `TelemetryDiagnosticCheckLedLitUpStateReply` as the argument of
// `ReplyToInquiry`
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticCheckLedLitUpStateInquiry {};

// Details regarding the inquiry to check the keyboard backlight lit up state.
// Clients should inspect the keyboard backlight and report its state using
// `TelemetryDiagnosticCheckKeyboardBacklightStateReply`.
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticCheckKeyboardBacklightStateInquiry {};

// An interaction that has to be replied to. Each inquiry type has a
// corresponding reply type in `TelemetryDiagnosticRoutineInquiryReply`. Clients
// should call the `ReplyToInquiry` method of
// `TelemetryDiagnosticRoutineControl` with the corresponding reply type.
//
// NextMinVersion: 3, NextIndex: 3
[Stable, Extensible]
union TelemetryDiagnosticRoutineInquiry {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedInquiry@0;
  // Details of the inquiry to check the LED lit up state.
  [MinVersion=1] TelemetryDiagnosticCheckLedLitUpStateInquiry
      check_led_lit_up_state@1;
  // Details of the inquiry to check the keyboard backlight LED state.
  [MinVersion=2]
  TelemetryDiagnosticCheckKeyboardBacklightStateInquiry
      check_keyboard_backlight_state@2;
};

// An interaction that is requested by a routine in the waiting state. See the
// comments on the subtypes to learn how to respond to each interaction request.
//
// Note: this union type contains only one field (apart from the unrecognized
// one) because all interactions currently need to be replied to. Another type
// `TelemetryDiagnosticRoutineTask` should be added when there are interactions
// that do not need to be replied to.
//
// NextMinVersion: 1, NextIndex: 2
[Stable, Extensible]
union TelemetryDiagnosticRoutineInteraction {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedInteraction@0;
  // An interaction that needs to be replied to using `ReplyToInquiry`.
  TelemetryDiagnosticRoutineInquiry inquiry@1;
};

// Routine is currently waiting.
//
// NextMinVersion: 2, NextIndex: 3
[Stable]
struct TelemetryDiagnosticRoutineStateWaiting {
  // The reason why the routine waits.
  //
  // NextMinVersion: 1, NextIndex: 3
  [Stable, Extensible]
  enum Reason {
    [Default] kUnmappedEnumField = 0,
    // Waiting for the job to be scheduled for running.
    kWaitingToBeScheduled = 1,
    // Waiting for an interaction. Check `interaction` to learn about which
    // interaction is requested.
    kWaitingForInteraction = 2,
  };
  // Reason why the routine waits.
  Reason reason@0;
  // Additional information, may be used to pass instruction or explanation.
  string message@1;
  // The requested interaction. This field is set if and only if `reason` is
  // kWaitingForInteraction. When set, clients must respond to the interaction
  // for the routine to proceed.
  [MinVersion=1] TelemetryDiagnosticRoutineInteraction? interaction@2;
};

// Enumeration of each possible memtester test item.
//
// NextMinVersion: 1, NextIndex: 20
[Stable, Extensible]
enum TelemetryDiagnosticMemtesterTestItemEnum {
  [Default] kUnmappedEnumField = 0,
  // The memtester test is not recognized.
  kUnknown = 1,

  // Test that all memory addresses to be tested can be set to itself and its
  // complement.
  kStuckAddress = 2,

  // These tests test different operation of a random int64 with buffer
  // initialized as 0xFFFFFFFF, repeating over 64 bit blocks.
  // Perform AND operation.
  kCompareAND = 3,
  // Perform DIV operation.
  kCompareDIV = 4,
  // Perform MUL operation.
  kCompareMUL = 5,
  // Perform OR operation.
  kCompareOR = 6,
  // Perform SUB operation.
  kCompareSUB = 7,
  // Perform XOR operation.
  kCompareXOR = 8,
  // Perform ADD operation.
  kSequentialIncrement = 9,

  // These tests test setting memory regions in a certain pattern, repeating
  // over each 64 bit blocks.
  // Test Pattern: |0*10*| and |1*01*|.
  kBitFlip = 10,
  // Test Pattern:|0*1010*| and |1*0101*|.
  kBitSpread = 11,
  // Test Pattern: all 256 possible combinations of a 8 bit block, repeated 8
  // times.
  kBlockSequential = 12,
  // Test Pattern: Alternating 0 and 1.
  kCheckerboard = 13,
  // Test Pattern: Random 64 bits.
  kRandomValue = 14,
  // Test Pattern: all 0s and all 1s.
  kSolidBits = 15,
  // Test Pattern: |0*10*|.
  kWalkingOnes = 16,
  // Test Pattern: |1*01*|.
  kWalkingZeroes = 17,

  // These tests test writing random n bit words across the memory regions.
  // Test Pattern: 8 bit random words.
  kEightBitWrites = 18,
  // Test Pattern: 16 bit random words.
  kSixteenBitWrites = 19,
};

// Result from running memtester.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticMemtesterResult {
  // Tests that have passed.
  array<TelemetryDiagnosticMemtesterTestItemEnum> passed_items@0;
  // Tests that have failed.
  array<TelemetryDiagnosticMemtesterTestItemEnum> failed_items@1;
};

// Details regarding memory routine.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticMemoryRoutineDetail {
  // Number of bytes tested in the memory routine.
  uint64 bytes_tested@0;
  // Contains the memtester test results.
  TelemetryDiagnosticMemtesterResult result@1;
};

// Details regarding volume button routine.
//
// NextMinVersion: 1, NextIndex: 0
[Stable]
struct TelemetryDiagnosticVolumeButtonRoutineDetail {};

// Whether the given hardware probed matches the hardware description recorded.
//
// NextMinVersion: 1, NextIndex: 4
[Stable, Extensible]
enum TelemetryDiagnosticHardwarePresenceStatus {
  // The default value is for backward compatibility, should not be used.
  [Default] kUnmappedEnumField = 0,
  // The hardware presence matches the description.
  kMatched = 1,
  // The hardware presence does not match the description.
  kNotMatched = 2,
  // There is no description available, skipping check.
  kNotConfigured = 3,
};

// Details regarding fan routine.
//
// NextMinVersion: 1, NextIndex: 3
[Stable]
struct TelemetryDiagnosticFanRoutineDetail {
  // The ids of fans that can be controlled.
  array<uint8> passed_fan_ids@0;
  // The ids of fans that cannot be controlled.
  array<uint8> failed_fan_ids@1;
  // Whether the number of fan probed is matched.
  TelemetryDiagnosticHardwarePresenceStatus fan_count_status@2;
};

// Details regarding network bandwidth routine.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticNetworkBandwidthRoutineDetail {
  // Average download speed in kbit/s.
  double download_speed_kbps@0;
  // Average upload speed in kbit/s.
  double upload_speed_kbps@1;
};

// All possible results for subtests of camera routines.
//
// NextMinVersion: 1, NextIndex: 4
[Stable, Extensible]
enum TelemetryDiagnosticCameraSubtestResult {
  // The default value is for backward compatibility, should not be used.
  [Default] kUnmappedEnumField = 0,
  // The subtest was not run, possibly because the subtest was not enabled in
  // the routine parameter or the subtest was not available on the device.
  kNotRun = 1,
  // The subtest was passed.
  kPassed = 2,
  // The subtest was failed.
  kFailed = 3,
};

// Details regarding camera frame analysis routine.
//
// NextMinVersion: 1, NextIndex: 3
[Stable]
struct TelemetryDiagnosticCameraFrameAnalysisRoutineDetail {
  // The first issue caught by the routine. See the fields for each subtest for
  // their details.
  //
  // NextMinVersion: 1, NextIndex: 5
  [Stable, Extensible]
  enum Issue {
    // For mojo backward compatibility, should not be used.
    [Default] kUnmappedEnumField = 0,
    // No issue.
    kNone = 1,
    // The camera service is not available.
    kCameraServiceNotAvailable = 2,
    // The len is blocked by the privacy shutter.
    kBlockedByPrivacyShutter = 3,
    // The frames are blurred. Lens might be dirty.
    kLensAreDirty = 4,
  };
  Issue issue@0;
  // The result is `kFailed` if the len is blocked by the privacy shutter. To
  // mitigate the issue, users are suggested to open the privacy shutter to
  // unveil the len.
  TelemetryDiagnosticCameraSubtestResult privacy_shutter_open_test@1;
  // The result is `kFailed` if the frames are blurred. To mitigate the issue,
  // users are suggested to clean the lens.
  TelemetryDiagnosticCameraSubtestResult lens_not_dirty_test@2;
};

// Details about a finished routine.
//
// NextMinVersion: 6, NextIndex: 6
[Stable, Extensible]
union TelemetryDiagnosticRoutineDetail {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedArgument@0;
  // Details of a completed memory routine.
  [MinVersion=1] TelemetryDiagnosticMemoryRoutineDetail memory@1;
  // Details of a completed volume button routine.
  [MinVersion=2] TelemetryDiagnosticVolumeButtonRoutineDetail volume_button@2;
  // Details of a completed fan routine.
  [MinVersion=3] TelemetryDiagnosticFanRoutineDetail fan@3;
  // Details of a completed network bandwidth routine.
  [MinVersion=4]
  TelemetryDiagnosticNetworkBandwidthRoutineDetail network_bandwidth@4;
  // Details of a completed camera frame analysis routine.
  [MinVersion=5]
  TelemetryDiagnosticCameraFrameAnalysisRoutineDetail camera_frame_analysis@5;
};

// Information about a finished routine.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticRoutineStateFinished {
  // Whether the routine has passed or not.
  bool has_passed@0;
  // The details of the routine.
  TelemetryDiagnosticRoutineDetail? detail@1;
};

// Possible routine states.
//
// NextMinVersion: 1, NextIndex: 4
[Stable]
union TelemetryDiagnosticRoutineStateUnion {
  // Default field is required by extensible unions for backward compatibility.
  // Any unrecognized Mojo field will deserialize to this field. Don't use this.
  [Default] bool unrecognizedArgument @0;
  // Routine has been initialized but not yet started.
  TelemetryDiagnosticRoutineStateInitialized initialized@1;
  // Routine is running.
  TelemetryDiagnosticRoutineStateRunning running@2;
  // Routine is waiting for something.
  TelemetryDiagnosticRoutineStateWaiting waiting@3;
  // Routine has finished.
  TelemetryDiagnosticRoutineStateFinished finished@4;
};

// Used to pass information regarding routine state.
//
// NextMinVersion: 1, NextIndex: 2
[Stable]
struct TelemetryDiagnosticRoutineState {
  // The percentage of the completion of the routine. 0 to 100.
  uint8 percentage@0;

  TelemetryDiagnosticRoutineStateUnion state_union@1;
};

// Interface exposed to clients for controlling a routine.
//
// Error Handling:
// Please check the Error Handling section of
// TelemetryDiagnosticRoutinesService.
//
// NextMinVersion: 3, NextIndex: 3
[Stable]
interface TelemetryDiagnosticRoutineControl {
  // Gets the current state of the routine. Note that if the routine fails to
  // initialize, the RoutineControl will disconnect before the callback is
  // called.
  [MinVersion=1] GetState@0() => (TelemetryDiagnosticRoutineState state);

  // Starts the routine. Each routine can only be started once. Calling this
  // method multiple times results in no-ops.
  //
  // See the error handling section above to know how to handle possible
  // exceptions that occur before and after the routine has been started.
  [MinVersion=1] Start@1();

  // Replies to the routine inquiry requested in the waiting state. The routine
  // will raise an exception (by closing the connection of this
  // `TelemetryDiagnosticRoutineControl`) if the routine is not in the waiting
  // state or the reply does not match the inquiry in the waiting state (see
  // `TelemetryDiagnosticRoutineStateWaiting`).
  [MinVersion=2] ReplyToInquiry@2(TelemetryDiagnosticRoutineInquiryReply reply);
};

// Implemented by clients who desire routine update notifications.
//
// NextMinVersion: 1, NextIndex: 1
[Stable]
interface TelemetryDiagnosticRoutineObserver {
  // Called when the routine state has changed. This is also called as soon
  // as a routine is initialized (right after calling `CreateRoutine`).
  // Note that if the routine fails to initialize, the
  // TelemetryDiagnosticRoutineControl may disconnect before the first
  // invocation of this observer method.
  [MinVersion=1] OnRoutineStateChange@0(TelemetryDiagnosticRoutineState state);
};

// Diagnostic Routines interface exposed to Lacros, implemented in Ash.
//
// NextMinVersion: 3, NextIndex: 2
[Stable, Uuid="0c7a9109-17eb-459d-82cd-60903bba315d"]
interface TelemetryDiagnosticRoutinesService {
  // Requests that a routine using the RoutineControl API is created on the
  // platform. This function creates a different routine based on the
  // RoutineArgument supplied.
  //
  // Error Handling:
  // This method will result in the creation of the routine on the device, which
  // might require allocation of additional resources and checking preconditions
  // for the routine, e.g. available hardware, correct arguments, etc.
  //
  // All exceptions that occur (either during initialization or while executing
  // the routine) will close the connection to the provided
  // TelemetryDiagnosticRoutineControl with a specific reason (see
  // crosapi.mojom.TelemetryExtensionException) and a string message containing
  // human readable information about the exception.
  // For that reason it is necessary to always setup a disconnect handler on the
  // TelemetryDiagnosticRoutineControl remote to be informed about potential
  // exceptions.
  //
  // Please note exceptions are different from a routine reporting `has_passed
  // == false` (in case it failed, see TelemetryDiagnosticRoutineStateFinished).
  // Exception are something not intended to happen. The details of the reasons
  // for Exceptions can be found in crosapi.mojom.TelemetryExtensionException
  // type and the corresponding reason enum.
  //
  // To know if an exception occurs during the initialization, callers can wait
  // for the routine being initialized (get via `GetState` or
  // TelemetryDiagnosticRoutineObserver) on the
  // TelemetryDiagnosticRoutineControl remote, before calling the `Start`
  // method.
  //
  // The request:
  // * |routine_argument| - a RoutineArgument type that provides all the
  //                        necessary parameters and configs to create a
  //                        particular type of routine.
  // * |routine_receiver| - a receiver that will be bound to the actual routine
  //                        control implementation, where the remote will be
  //                        held by the client for starting the routine.
  //
  // * |routine_observer| - an optional observer to receive status updates about
  //                        changing routine states.
  [MinVersion=1] CreateRoutine@0(
      TelemetryDiagnosticRoutineArgument routine_argument,
      pending_receiver<TelemetryDiagnosticRoutineControl> routine_receiver,
      pending_remote<TelemetryDiagnosticRoutineObserver>? routine_observer);

  // Checks whether a given `TelemetryDiagnosticRoutineArgument` is supported.
  //
  // The request:
  // * |routine_argument| - a TelemetryDiagnosticRoutineArgument type that
  //                        provides all the necessary parameters to create a
  //                        particular type of routine.
  //
  // The response:
  // * |status| - See the documentation of `TelemetryExtensionSupportStatus`.
  [MinVersion=2] IsRoutineArgumentSupported@1(
      TelemetryDiagnosticRoutineArgument routine_argument) =>
        (TelemetryExtensionSupportStatus status);
};