এপিআই হিসেবে সিস্টেম প্রপার্টি ইমপ্লিমেন্ট করা, এপিআই হিসেবে সিস্টেম প্রপার্টি ইমপ্লিমেন্ট করা

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

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

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

Sysprop বর্ণনা ফাইল ( .sysprop ) সহ এপিআই হিসাবে সিস্টেম বৈশিষ্ট্যগুলিকে সংজ্ঞায়িত করুন, যা নিম্নলিখিত স্কিমা সহ প্রোটোবাফের একটি টেক্সটফরম্যাট ব্যবহার করে:

// 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 হবে নেমস্পেস com::android::sysprop::BuildProperties এবং জাভাতে com.android.sysprop এর প্যাকেজে BuildProperties ক্লাস।
prop সম্পত্তির তালিকা।

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

মাঠ অর্থ
api_name উৎপন্ন API এর নাম।
type এই সম্পত্তির ধরন.
access Readonly : শুধুমাত্র গেটার API তৈরি করে

Writeonce , ReadWrite : গেটার এবং সেটার API তৈরি করে

দ্রষ্টব্য: উপসর্গ ro. ReadWrite অ্যাক্সেস ব্যবহার নাও করতে পারে।

scope Internal : শুধুমাত্র মালিক অ্যাক্সেস করতে পারেন।

Public : NDK মডিউল ব্যতীত সবাই অ্যাক্সেস করতে পারে।

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

প্রতিটি ধরনের সম্পত্তি C++, Java এবং Rust-এ নিম্নলিখিত ধরনের ম্যাপ করে।

টাইপ সি++ জাভা মরিচা
বুলিয়ান std::optional<bool> Optional<Boolean> bool
পূর্ণসংখ্যা std::optional<std::int32_t> Optional<Integer> i32
UInt std::optional<std::uint32_t> Optional<Integer> u32
লম্বা std::optional<std::int64_t> Optional<Long> i64
উলং std::optional<std::uint64_t> Optional<Long> u64
ডাবল std::optional<double> Optional<Double> f64
স্ট্রিং std::optional<std::string> Optional<String> String
এনাম std::optional<{api_name}_values> Optional<{api_name}_values> {ApiName}Values
টি তালিকা std::vector<std::optional<T>> List<T> Vec<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 বর্ণনা ফাইলের সাথে 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 ডিরেক্টরি তৈরি করুন। 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

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

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

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

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

মনে রাখবেন যে মরিচা লাইব্রেরি নামটি sysprop_library নামটিকে ছোট হাতের অক্ষরে রূপান্তর করে, প্রতিস্থাপন করে তৈরি করা হয় . এবং - এর সাথে _ , এবং তারপর lib এবং _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
        );
    }
    …
}
…

C++ উদাহরণ:

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