APIs হিসাবে সিস্টেম বৈশিষ্ট্য প্রয়োগ করুন

সিস্টেম প্রোপার্টি (sysprops) সিস্টেম-ব্যাপী তথ্য, সাধারণত কনফিগারেশন, ভাগ করে নেওয়ার একটি সুবিধাজনক উপায় প্রদান করে। প্রতিটি পার্টিশন অভ্যন্তরীণভাবে তার নিজস্ব সিস্টেম প্রোপার্টি ব্যবহার করতে পারে। যখন /vendor অ্যাক্সেসিং /system সংজ্ঞায়িত প্রোপার্টিগুলির মতো পার্টিশন জুড়ে প্রোপার্টি অ্যাক্সেস করা হয় তখন সমস্যা হতে পারে। Android 8.0 থেকে, কিছু পার্টিশন, যেমন /system , আপগ্রেড করা যেতে পারে, যখন /vendor অপরিবর্তিত রাখা হয়। যেহেতু সিস্টেম প্রোপার্টিগুলি কেবল স্ট্রিং কী-মান জোড়ার একটি বিশ্বব্যাপী অভিধান যার কোনও স্কিমা নেই, তাই প্রোপার্টিগুলি স্থিতিশীল করা কঠিন। /system পার্টিশন কোনও বিজ্ঞপ্তি ছাড়াই /vendor পার্টিশনের উপর নির্ভর করে এমন প্রোপার্টিগুলি পরিবর্তন বা অপসারণ করতে পারে।

অ্যান্ড্রয়েড ১০ এবং তার পরবর্তী সংস্করণে, পার্টিশন জুড়ে অ্যাক্সেস করা সিস্টেম বৈশিষ্ট্যগুলিকে sysprop বর্ণনা ফাইলে স্কিম্যাটাইজ করা হয় এবং বৈশিষ্ট্যগুলি অ্যাক্সেস করার জন্য APIগুলি C++ এবং Rust এর জন্য কংক্রিট ফাংশন এবং Java এর জন্য ক্লাস হিসাবে তৈরি করা হয়। এই APIগুলি ব্যবহার করা আরও সুবিধাজনক কারণ অ্যাক্সেসের জন্য কোনও ম্যাজিক স্ট্রিং (যেমন ro.build.date ) প্রয়োজন হয় না এবং কারণ এগুলি স্ট্যাটিক্যালি টাইপ করা যায়। বিল্ডের সময় ABI স্থিতিশীলতাও পরীক্ষা করা হয় এবং অসঙ্গতিপূর্ণ পরিবর্তনগুলি ঘটলে বিল্ড ভেঙে যায়। এই চেকটি পার্টিশনের মধ্যে স্পষ্টভাবে সংজ্ঞায়িত ইন্টারফেস হিসাবে কাজ করে। এই APIগুলি রাস্ট, জাভা এবং C++ এর মধ্যে সামঞ্জস্যও প্রদান করতে পারে।

সিস্টেমের বৈশিষ্ট্যগুলিকে API হিসেবে সংজ্ঞায়িত করুন

সিস্টেম প্রোপার্টিগুলিকে Sysprop Description ফাইল ( .sysprop ) সহ API হিসাবে সংজ্ঞায়িত করুন, যা নিম্নলিখিত স্কিমা সহ protobuf এর একটি TextFormat ব্যবহার করে:

// 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++) অথবা স্ট্যাটিক ফাইনাল ক্লাস (জাভা) তৈরি করতে ব্যবহৃত হয় যেখানে জেনারেট করা API গুলি স্থাপন করা হয়। উদাহরণস্বরূপ, com.android.sysprop.BuildProperties হল C++ তে namespace com::android::sysprop::BuildProperties , এবং জাভা তে com.android.sysprop প্যাকেজে BuildProperties ক্লাস।
prop সম্পত্তির তালিকা।

Property বার্তা ক্ষেত্রগুলির অর্থ নিম্নরূপ:

মাঠ অর্থ
api_name তৈরি করা API এর নাম।
type এই সম্পত্তির ধরণ।
access Readonly : শুধুমাত্র গেটার API তৈরি করে
Writeonce , ReadWrite : গেটার এবং সেটার API তৈরি করে
scope Internal : শুধুমাত্র মালিক অ্যাক্সেস করতে পারবেন।
Public : NDK মডিউল ব্যতীত সকলেই অ্যাক্সেস করতে পারবেন।
prop_name অন্তর্নিহিত সিস্টেম বৈশিষ্ট্যের নাম, উদাহরণস্বরূপ ro.build.date
enum_values ( Enum , শুধুমাত্র EnumList ) একটি bar(|)-বিচ্ছিন্ন স্ট্রিং যাতে সম্ভাব্য enum মান থাকে। উদাহরণস্বরূপ, value1|value2
integer_as_bool ( Boolean , শুধুমাত্র BooleanList ) সেটারদের false এবং true এর পরিবর্তে 0 এবং 1 ব্যবহার করতে দিন।
legacy_prop_name (ঐচ্ছিক, শুধুমাত্র Readonly বৈশিষ্ট্য) অন্তর্নিহিত সিস্টেম সম্পত্তির লিগ্যাসি নাম। গেটার কল করার সময়, গেটার API prop_name পড়ার চেষ্টা করে এবং prop_name বিদ্যমান না থাকলে legacy_prop_name ব্যবহার করে। বিদ্যমান সম্পত্তি অবচয় করার সময় এবং একটি নতুন সম্পত্তিতে স্থানান্তর করার সময় legacy_prop_name ব্যবহার করুন।

প্রতিটি ধরণের সম্পত্তি C++, জাভা এবং রাস্টে নিম্নলিখিত ধরণের সাথে ম্যাপ করে:

আদর্শ সি++ (বাতিলযোগ্য) জাভা (খারাপ) মরিচা (ঐচ্ছিক বা বাতিলযোগ্য)
বুলিয়ান std::optional<bool> Optional<Boolean> Option<bool>
পূর্ণসংখ্যা std::optional<std::int32_t> Optional<Integer> Option<i32>
ইউআইএনটি std::optional<std::uint32_t> Optional<Integer> Option<u32>
দীর্ঘ std::optional<std::int64_t> Optional<Long> Option<i64>
উলং std::optional<std::uint64_t> Optional<Long> Option<u64>
দ্বিগুণ std::optional<double> Optional<Double> Option<f64>
স্ট্রিং std::optional<std::string> Optional<String> Option<String>
এনাম std::optional<{api\_name}\_values> Optional<{api\_name}\_values> Option<{ApiName}Values>
টি তালিকা std::vector<std::optional<T>> List<T> Vec<T>

এখানে একটি Sysprop Description ফাইলের উদাহরণ দেওয়া হল যা তিনটি বৈশিষ্ট্য সংজ্ঞায়িত করে:

# 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 Description ফাইল ব্যবহার করে আপনি sysprop_library মডিউল সংজ্ঞায়িত করতে পারেন। sysprop_library C++, Java এবং Rust এর জন্য API হিসেবে কাজ করে। বিল্ড সিস্টেম অভ্যন্তরীণভাবে sysprop_library এর প্রতিটি উদাহরণের জন্য একটি rust_library , একটি java_library এবং একটি cc_library তৈরি করে।

// File: Android.bp
sysprop_library {
    name: "PlatformProperties",
    srcs: ["android/sysprop/PlatformProperties.sysprop"],
    property_owner: "Platform",
    vendor_available: true,
}

API চেকের জন্য সোর্সে API তালিকা ফাইল অন্তর্ভুক্ত করতে হবে। এটি করার জন্য, API ফাইল এবং একটি api ডিরেক্টরি তৈরি করুন। Android.bp এর মতো একই ডিরেক্টরিতে api ডিরেক্টরি রাখুন। 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

রাস্ট, জাভা এবং সি++ ক্লায়েন্ট মডিউলগুলি জেনারেটেড এপিআই ব্যবহার করার জন্য sysprop_library এর সাথে লিঙ্ক করতে পারে। বিল্ড সিস্টেমটি ক্লায়েন্ট থেকে জেনারেটেড সি++, জাভা এবং রাস্ট লাইব্রেরিতে লিঙ্ক তৈরি করে, যার ফলে ক্লায়েন্টদের জেনারেটেড এপিআইগুলিতে অ্যাক্সেস দেওয়া হয়।

java_library {
    name: "JavaClient",
    srcs: ["foo/bar.java"],
    libs: ["PlatformProperties"],
}

cc_binary {
    name: "cc_client",
    srcs: ["baz.cpp"],
    shared_libs: ["libPlatformProperties"],
}

rust_binary {
    name: "rust_client",
    srcs: ["src/main.rs"],
    rustlibs: ["libplatformproperties_rust"],
}

পূর্ববর্তী উদাহরণে, আপনি নিম্নরূপ সংজ্ঞায়িত বৈশিষ্ট্যগুলি অ্যাক্সেস করতে পারেন।

মরিচা উদাহরণ:

use platformproperties::DeviceStatusValues;

fn foo() -> Result<(), Error> {
  // Read "ro.build.date_utc". default value is -1.
  let date_utc = platformproperties::date_utc()?.unwrap_or_else(-1);

  // set "device.status" to "unknown" if "ro.build.date" is not set.
  if platformproperties::build_date()?.is_none() {
    platformproperties::set_device_status(DeviceStatusValues::UNKNOWN);
  }

  
}

জাভা উদাহরণ:

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);
    }
    
}