Системные свойства обеспечивают удобный способ обмена информацией, обычно конфигурациями, в рамках всей системы. Каждый раздел может использовать свои собственные системные свойства внутри. Проблема может возникнуть, когда доступ к свойствам осуществляется через разделы, например, /vendor обращается к свойствам, определенным /system . Начиная с Android 8.0, некоторые разделы, такие как /system , можно обновить, а /vendor оставить без изменений. Поскольку системные свойства представляют собой просто глобальный словарь строковых пар ключ/значение без схемы, стабилизировать свойства сложно. Раздел /system может изменить или удалить свойства, от которых зависит раздел /vendor без предварительного уведомления.
 Начиная с выпуска Android 10 системные свойства, доступ к которым осуществляется через разделы, схематизированы в файлы описания Sysprop, а API для доступа к свойствам создаются в виде конкретных функций для C++ и классов для Java. Эти API более удобны в использовании, поскольку для доступа не требуются волшебные строки (такие как ro.build.date ), а также потому, что они могут быть статически типизированы. Стабильность ABI также проверяется во время сборки, и сборка прерывается, если происходят несовместимые изменения. Эта проверка действует как явно определенные интерфейсы между разделами. Эти API также могут обеспечить согласованность между Java и C++.
Определение свойств системы как API
 Определите системные свойства как API с файлами описания Sysprop ( .sysprop ), которые используют TextFormat protobuf со следующей схемой:
// File: sysprop.proto
syntax = "proto3";
package sysprop;
enum Access {
  Readonly = 0;
  Writeonce = 1;
  ReadWrite = 2;
}
enum Owner {
  Platform = 0;
  Vendor = 1;
  Odm = 2;
}
enum Scope {
  Public = 0;
  Internal = 2;
}
enum Type {
  Boolean = 0;
  Integer = 1;
  Long = 2;
  Double = 3;
  String = 4;
  Enum = 5;
  UInt = 6;
  ULong = 7;
  BooleanList = 20;
  IntegerList = 21;
  LongList = 22;
  DoubleList = 23;
  StringList = 24;
  EnumList = 25;
  UIntList = 26;
  ULongList = 27;
}
message Property {
  string api_name = 1;
  Type type = 2;
  Access access = 3;
  Scope scope = 4;
  string prop_name = 5;
  string enum_values = 6;
  bool integer_as_bool = 7;
  string legacy_prop_name = 8;
}
message Properties {
  Owner owner = 1;
  string module = 2;
  repeated Property prop = 3;
}
Один файл описания Sysprop содержит одно сообщение о свойствах, описывающее набор свойств. Смысл его полей следующий.
| Поле | Имея в виду | 
|---|---|
 owner |  Установите раздел, которому принадлежат свойства: Platform , Vendor или Odm . | 
 module |  Используется для создания пространства имен (C++) или статического конечного класса (Java), в котором размещаются сгенерированные API. Например, com.android.sysprop.BuildProperties будет пространством имен com::android::sysprop::BuildProperties в C++ и классом BuildProperties в пакете com.android.sysprop в Java. | 
 prop | Список свойств. | 
 Значения полей сообщений Property следующие.
| Поле | Имея в виду | 
|---|---|
 api_name | Имя сгенерированного API. | 
 type | Тип этого свойства. | 
 access |  Readonly : генерирует только API геттера.   Примечание. Свойства с префиксом   | 
 scope |  Internal : доступ есть только у владельца.   | 
 prop_name |  Имя базового системного свойства, например ro.build.date . | 
 enum_values |  ( Только Enum , EnumList ) Разделенная чертой (|) строка, состоящая из возможных значений перечисления. Например, value1|value2 . | 
 integer_as_bool |  ( только Boolean , BooleanList ) Заставьте установщики использовать 0 и 1 вместо false и true . | 
 legacy_prop_name |  (необязательно, Readonly свойства только для чтения) Устаревшее имя базового системного свойства. При вызове getter API-интерфейс getter пытается прочитать prop_name и использует legacy_prop_name , если prop_name не существует. Используйте legacy_prop_name при прекращении поддержки существующего свойства и переходе к новому свойству. | 
Каждый тип свойства сопоставляется со следующими типами в C++ и Java.
| Тип | С++ | Джава | 
|---|---|---|
| логический |  std::optional<bool> |  Optional<Boolean> | 
| Целое число |  std::optional<std::int32_t> |  Optional<Integer> | 
| UInt |  std::optional<std::uint32_t> |  Optional<Integer> | 
| Длинная |  std::optional<std::int64_t> |  Optional<Long> | 
| Улонг |  std::optional<std::uint64_t> |  Optional<Long> | 
| Двойной |  std::optional<double> |  Optional<Double> | 
| Нить |  std::optional<std::string> |  Optional<String> | 
| перечисление |  std::optional<{api_name}_values> |  Optional<{api_name}_values> | 
| Список Т |  std::vector<std::optional<T>> |  List<T> | 
Вот пример файла описания Sysprop, определяющего три свойства:
# File: android/sysprop/PlatformProperties.sysprop
owner: Platform
module: "android.sysprop.PlatformProperties"
prop {
    api_name: "build_date"
    type: String
    prop_name: "ro.build.date"
    scope: Public
    access: Readonly
}
prop {
    api_name: "date_utc"
    type: Integer
    prop_name: "ro.build.date_utc"
    scope: Internal
    access: Readonly
}
prop {
    api_name: "device_status"
    type: Enum
    enum_values: "on|off|unknown"
    prop_name: "device.status"
    scope: Public
    access: ReadWrite
}
Определение библиотек свойств системы
 Теперь вы можете определять модули sysprop_library с файлами описания Sysprop. sysprop_library служит API как для C++, так и для Java. Система сборки внутри генерирует одну java_library и одну cc_library для каждого экземпляра sysprop_library .
// File: Android.bp
sysprop_library {
    name: "PlatformProperties",
    srcs: ["android/sysprop/PlatformProperties.sysprop"],
    property_owner: "Platform",
    vendor_available: true,
}
 Вы должны включить файлы списков API в источник для проверки API. Для этого создайте файлы API и каталог api . Поместите каталог api в тот же каталог, что и Android.bp . Имена файлов API: <module_name>-current.txt , <module_name>-latest.txt . <module_name>-current.txt содержит подписи API текущих исходных кодов, а <module_name>-latest.txt содержит последние замороженные подписи API. Система сборки проверяет, были ли изменены API, сравнивая эти файлы API с сгенерированными файлами API во время сборки, и выдает сообщение об ошибке и инструкции по обновлению файла current.txt , если current.txt не соответствует исходным кодам. Вот пример каталога и файловой организации:
├── api
│   ├── PlatformProperties-current.txt
│   └── PlatformProperties-latest.txt
└── Android.bp
 Клиентские модули Java и C++ могут связываться с sysprop_library для использования сгенерированных API. Система сборки создает ссылки от клиентов на сгенерированные библиотеки C++ и Java, тем самым предоставляя клиентам доступ к сгенерированным API.
java_library {
    name: "JavaClient",
    srcs: ["foo/bar.java"],
    libs: ["PlatformProperties"],
}
cc_binary {
    name: "cc_client",
    srcs: ["baz.cpp"],
    shared_libs: ["PlatformProperties"],
}
В приведенном выше примере вы можете получить доступ к определенным свойствам следующим образом.
Пример Java:
import android.sysprop.PlatformProperties;
…
static void foo() {
    …
    // read "ro.build.date_utc". default value is -1
    Integer dateUtc = PlatformProperties.date_utc().orElse(-1);
    // set "device.status" to "unknown" if "ro.build.date" is not set
    if (!PlatformProperties.build_date().isPresent()) {
        PlatformProperties.device_status(
            PlatformProperties.device_status_values.UNKNOWN
        );
    }
    …
}
…
Пример С++:
#include <android/sysprop/PlatformProperties.sysprop.h>
using namespace android::sysprop;
…
void bar() {
    …
    // read "ro.build.date". default value is "(unknown)"
    std::string build_date = PlatformProperties::build_date().value_or("(unknown)");
    // set "device.status" to "on" if it's "unknown" or not set
    using PlatformProperties::device_status_values;
    auto status = PlatformProperties::device_status();
    if (!status.has_value() || status.value() == device_status_values::UNKNOWN) {
        PlatformProperties::device_status(device_status_values::ON);
    }
    …
}
…