গাড়ির ক্যামেরা HAL

অ্যান্ড্রয়েডে একটি স্বয়ংচালিত HIDL হার্ডওয়্যার অ্যাবস্ট্রাকশন লেয়ার (HAL) রয়েছে যা অ্যান্ড্রয়েড বুট প্রক্রিয়ার খুব প্রথম দিকে ইমেজ ক্যাপচার এবং প্রদর্শনের জন্য প্রদান করে এবং সিস্টেমের জীবনের জন্য কাজ চালিয়ে যায়। HAL-এ এক্সটেরিয়র ভিউ সিস্টেম (EVS) স্ট্যাক রয়েছে এবং সাধারণত Android-ভিত্তিক ইন-ভেহিক্যাল ইনফোটেইনমেন্ট (IVI) সিস্টেমের সাথে গাড়িতে রিয়ারভিউ ক্যামেরা এবং চারপাশের দৃশ্য প্রদর্শন সমর্থন করতে ব্যবহৃত হয়। EVS ব্যবহারকারীর অ্যাপগুলিতে প্রয়োগ করা উন্নত বৈশিষ্ট্যগুলিকে সক্ষম করে।

অ্যান্ড্রয়েড-এ একটি EVS-নির্দিষ্ট ক্যাপচার এবং ডিসপ্লে ড্রাইভার ইন্টারফেসও রয়েছে ( /hardware/interfaces/automotive/evs/1.0 এ)। যদিও বিদ্যমান অ্যান্ড্রয়েড ক্যামেরা এবং ডিসপ্লে পরিষেবাগুলির উপরে একটি রিয়ারভিউ ক্যামেরা অ্যাপ তৈরি করা সম্ভব, তবে এই জাতীয় অ্যাপ সম্ভবত অ্যান্ড্রয়েড বুট প্রক্রিয়াতে খুব দেরিতে চলবে। একটি ডেডিকেটেড HAL ব্যবহার করা একটি সুবিন্যস্ত ইন্টারফেস সক্ষম করে এবং ইভিএস স্ট্যাককে সমর্থন করার জন্য একটি OEM-এর কী প্রয়োগ করতে হবে তা স্পষ্ট করে তোলে।

সিস্টেম উপাদান

EVS নিম্নলিখিত সিস্টেম উপাদান অন্তর্ভুক্ত:

ইভিএস সিস্টেম উপাদান চিত্র
চিত্র 1. EVS সিস্টেম উপাদান ওভারভিউ।

ইভিএস অ্যাপ

একটি নমুনা C++ EVS অ্যাপ ( /packages/services/Car/evs/app ) একটি রেফারেন্স বাস্তবায়ন হিসেবে কাজ করে। এই অ্যাপটি ইভিএস ম্যানেজার থেকে ভিডিও ফ্রেম অনুরোধ করার জন্য এবং ইভিএস ম্যানেজারের কাছে প্রদর্শনের জন্য সমাপ্ত ফ্রেম পাঠানোর জন্য দায়ী৷ এটি ইভিএস এবং গাড়ি পরিষেবা উপলব্ধ হওয়ার সাথে সাথেই init দ্বারা শুরু হবে বলে আশা করে, পাওয়ার চালু হওয়ার দুই (2) সেকেন্ডের মধ্যে লক্ষ্য করে৷ OEM গুলি ইভিএস অ্যাপটিকে ইচ্ছামতো পরিবর্তন বা প্রতিস্থাপন করতে পারে৷

ইভিএস ম্যানেজার

EVS ম্যানেজার ( /packages/services/Car/evs/manager ) একটি সাধারণ রিয়ারভিউ ক্যামেরা ডিসপ্লে থেকে 6DOF মাল্টি-ক্যামেরা রেন্ডারিং পর্যন্ত যেকোনো কিছু বাস্তবায়ন করতে একটি EVS অ্যাপের প্রয়োজনীয় বিল্ডিং ব্লক সরবরাহ করে। এর ইন্টারফেস HIDL এর মাধ্যমে উপস্থাপিত হয় এবং একাধিক সমসাময়িক ক্লায়েন্ট গ্রহণ করার জন্য তৈরি করা হয়। অন্যান্য অ্যাপ এবং পরিষেবাগুলি (বিশেষত গাড়ি পরিষেবা) EVS সিস্টেম কখন সক্রিয় আছে তা খুঁজে বের করতে EVS ব্যবস্থাপকের অবস্থা জিজ্ঞাসা করতে পারে।

EVS HIDL ইন্টারফেস

EVS সিস্টেম, ক্যামেরা এবং ডিসপ্লে উপাদান উভয়ই android.hardware.automotive.evs প্যাকেজে সংজ্ঞায়িত করা হয়েছে। একটি নমুনা বাস্তবায়ন যা ইন্টারফেসের অনুশীলন করে (সিন্থেটিক পরীক্ষার চিত্র তৈরি করে এবং চিত্রগুলিকে রাউন্ড ট্রিপ করে যাচাই করে) /hardware/interfaces/automotive/evs/1.0/default এ সরবরাহ করা হয়েছে।

/hardware/interfaces/automotive/evs এ .hal ফাইল দ্বারা প্রকাশ করা API বাস্তবায়নের জন্য OEM দায়ী। এই ধরনের বাস্তবায়নগুলি ফিজিক্যাল ক্যামেরা থেকে ডেটা কনফিগার এবং সংগ্রহ করার জন্য দায়ী এবং এটি Gralloc দ্বারা স্বীকৃত শেয়ার্ড মেমরি বাফারের মাধ্যমে বিতরণ করা। বাস্তবায়নের ডিসপ্লে সাইড একটি শেয়ার্ড মেমরি বাফার প্রদানের জন্য দায়ী যা অ্যাপ দ্বারা পূরণ করা যেতে পারে (সাধারণত EGL রেন্ডারিং সহ) এবং ফিজিক্যাল ডিসপ্লেতে প্রদর্শিত হতে পারে এমন অন্য যেকোন কিছুর চেয়ে সমাপ্ত ফ্রেমগুলিকে উপস্থাপন করা। EVS ইন্টারফেসের বিক্রেতা বাস্তবায়ন /vendor/… /device/… অথবা hardware/… (যেমন, /hardware/[vendor]/[platform]/evs ) এর অধীনে সংরক্ষণ করা যেতে পারে।

কার্নেল ড্রাইভার

EVS স্ট্যাক সমর্থন করে এমন একটি ডিভাইসের জন্য কার্নেল ড্রাইভার প্রয়োজন। নতুন ড্রাইভার তৈরি করার পরিবর্তে, OEM-এর কাছে বিদ্যমান ক্যামেরা বা ডিসপ্লে হার্ডওয়্যার ড্রাইভারের মাধ্যমে EVS-প্রয়োজনীয় বৈশিষ্ট্যগুলিকে সমর্থন করার বিকল্প রয়েছে। ড্রাইভার পুনঃব্যবহার করা সুবিধাজনক হতে পারে, বিশেষ করে ডিসপ্লে ড্রাইভারের জন্য যেখানে চিত্র উপস্থাপনের জন্য অন্যান্য সক্রিয় থ্রেডের সাথে সমন্বয়ের প্রয়োজন হতে পারে। Android 8.0-এ একটি v4l2-ভিত্তিক নমুনা ড্রাইভার রয়েছে ( packages/services/Car/evs/sampleDriver এ) যা v4l2 সমর্থনের জন্য কার্নেলের উপর এবং আউটপুট চিত্র উপস্থাপনের জন্য SurfaceFlinger-এর উপর নির্ভর করে।

EVS হার্ডওয়্যার ইন্টারফেসের বিবরণ

বিভাগটি HAL বর্ণনা করে। বিক্রেতারা তাদের হার্ডওয়্যারের জন্য অভিযোজিত এই API এর বাস্তবায়ন প্রদান করবে বলে আশা করা হচ্ছে।

IEvs গণনাকারী

এই বস্তুটি সিস্টেমে উপলব্ধ ইভিএস হার্ডওয়্যার (এক বা একাধিক ক্যামেরা এবং একক প্রদর্শন ডিভাইস) গণনা করার জন্য দায়ী।

getCameraList() generates (vec<CameraDesc> cameras);

সিস্টেমের সমস্ত ক্যামেরার বিবরণ সহ একটি ভেক্টর প্রদান করে। ধারণা করা হয় ক্যামেরার সেট স্থির এবং বুট করার সময় জানা যায়। ক্যামেরার বিবরণের বিস্তারিত জানার জন্য, CameraDesc দেখুন।

openCamera(string camera_id) generates (IEvsCamera camera);

অনন্য camera_id স্ট্রিং দ্বারা চিহ্নিত একটি নির্দিষ্ট ক্যামেরার সাথে ইন্টারঅ্যাক্ট করতে ব্যবহৃত একটি ইন্টারফেস অবজেক্ট পায়। ব্যর্থ হলে একটি NULL প্রদান করে। ইতিমধ্যে খোলা একটি ক্যামেরা পুনরায় খোলার প্রচেষ্টা ব্যর্থ হতে পারে না৷ অ্যাপ স্টার্টআপ এবং শাটডাউনের সাথে সম্পর্কিত রেসের অবস্থা এড়াতে, একটি ক্যামেরা পুনরায় খোলার পূর্ববর্তী উদাহরণটি বন্ধ করা উচিত যাতে নতুন অনুরোধটি পূরণ করা যায়। এইভাবে প্রিম্পট করা একটি ক্যামেরা ইন্সট্যান্স অবশ্যই একটি নিষ্ক্রিয় অবস্থায় রাখতে হবে, চূড়ান্ত ধ্বংসের অপেক্ষায় এবং OWNERSHIP_LOST এর রিটার্ন কোড সহ ক্যামেরার অবস্থাকে প্রভাবিত করার যেকোনো অনুরোধে সাড়া দিতে হবে।

closeCamera(IEvsCamera camera);

IEvsCamera ইন্টারফেস প্রকাশ করে (এবং openCamera() কলের বিপরীত)। closeCamera কল করার আগে stopVideoStream() কল করে ক্যামেরা ভিডিও স্ট্রিম বন্ধ করতে হবে।

openDisplay() generates (IEvsDisplay display);

সিস্টেমের EVS প্রদর্শনের সাথে একচেটিয়াভাবে ইন্টারফেস করতে ব্যবহৃত একটি ইন্টারফেস অবজেক্ট পায়। শুধুমাত্র একজন ক্লায়েন্ট সময়ে IEvsDisplay এর একটি কার্যকরী উদাহরণ ধারণ করতে পারে। openCamera তে বর্ণিত আক্রমনাত্মক খোলা আচরণের অনুরূপ, একটি নতুন IEvsDisplay অবজেক্ট যে কোনো সময় তৈরি করা যেতে পারে এবং যে কোনো পূর্ববর্তী দৃষ্টান্তগুলিকে নিষ্ক্রিয় করে। অবৈধ দৃষ্টান্তগুলি বিদ্যমান থাকে এবং তাদের মালিকদের কাছ থেকে ফাংশন কলগুলিতে সাড়া দেয়, তবে মৃত অবস্থায় কোনও মিউটেটিং অপারেশন করতে হবে না। অবশেষে, ক্লায়েন্ট অ্যাপটি OWNERSHIP_LOST ত্রুটি রিটার্ন কোডগুলি লক্ষ্য করবে এবং নিষ্ক্রিয় ইন্টারফেসটি বন্ধ করে ছেড়ে দেবে বলে আশা করা হচ্ছে।

closeDisplay(IEvsDisplay display);

IEvsDisplay ইন্টারফেস প্রকাশ করে (এবং openDisplay() কলের বিপরীত)। getTargetBuffer() কলের সাথে প্রাপ্ত অসামান্য বাফারগুলি ডিসপ্লে বন্ধ করার আগে অবশ্যই ডিসপ্লেতে ফেরত দিতে হবে।

getDisplayState() generates (DisplayState state);

বর্তমান প্রদর্শন অবস্থা পায়। এইচএএল বাস্তবায়নের প্রকৃত বর্তমান অবস্থার রিপোর্ট করা উচিত, যা সাম্প্রতিক অনুরোধ করা অবস্থা থেকে ভিন্ন হতে পারে। ডিসপ্লে অবস্থা পরিবর্তনের জন্য দায়ী যুক্তিটি ডিভাইস স্তরের উপরে থাকা উচিত, এটি HAL বাস্তবায়নের জন্য স্বতঃস্ফূর্তভাবে প্রদর্শনের অবস্থা পরিবর্তন করা অবাঞ্ছিত করে তোলে। যদি ডিসপ্লেটি বর্তমানে কোনো ক্লায়েন্টের কাছে না থাকে (ওপেনডিসপ্লেতে কল করে), তাহলে এই ফাংশনটি NOT_OPEN প্রদান করে। অন্যথায়, এটি ইভিএস ডিসপ্লের বর্তমান অবস্থা রিপোর্ট করে ( IEvsDisplay API দেখুন)।

struct CameraDesc {
    string      camera_id;
    int32       vendor_flags;       // Opaque value
}
  • camera_id । একটি স্ট্রিং যা একটি প্রদত্ত ক্যামেরাকে অনন্যভাবে সনাক্ত করে৷ ডিভাইসের কার্নেল ডিভাইসের নাম বা ডিভাইসের নাম হতে পারে, যেমন রিয়ারভিউ । এই স্ট্রিংয়ের মানটি HAL বাস্তবায়ন দ্বারা নির্বাচিত হয় এবং উপরের স্ট্যাকের দ্বারা অস্বচ্ছভাবে ব্যবহৃত হয়।
  • vendor_flags ড্রাইভার থেকে একটি কাস্টম EVS অ্যাপে অস্বচ্ছভাবে বিশেষ ক্যামেরা তথ্য পাস করার একটি পদ্ধতি। এটি ড্রাইভার থেকে EVS অ্যাপ পর্যন্ত অব্যক্ত করা হয়, যা এটিকে উপেক্ষা করার জন্য বিনামূল্যে।

আইইভিএস ক্যামেরা

এই বস্তুটি একটি একক ক্যামেরা প্রতিনিধিত্ব করে এবং এটি ছবি তোলার জন্য প্রাথমিক ইন্টারফেস।

getCameraInfo() generates (CameraDesc info);

এই ক্যামেরার CameraDesc প্রদান করে।

setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);

ক্যামেরাকে সমর্থন করতে বলা হয় বাফার চেইনের গভীরতা নির্দিষ্ট করে। এই পর্যন্ত অনেকগুলি ফ্রেম IEvsCamera-এর ক্লায়েন্ট দ্বারা একযোগে রাখা হতে পারে। doneWithFrame দ্বারা প্রত্যাবর্তন না করে যদি এই অনেকগুলি ফ্রেম রিসিভারের কাছে বিতরণ করা হয়, তবে স্ট্রিমটি ফ্রেমগুলিকে এড়িয়ে যায় যতক্ষণ না একটি বাফার পুনরায় ব্যবহারের জন্য ফেরত দেওয়া হয়। এই কলটি যেকোন সময়ে আসা বৈধ, এমনকি স্ট্রীমগুলি ইতিমধ্যেই চলমান থাকা অবস্থায়ও, সেই ক্ষেত্রে বাফারগুলিকে যথাযত চেইন থেকে যুক্ত করা বা সরানো উচিত৷ যদি এই এন্ট্রি পয়েন্টে কোনো কল না করা হয়, IEvsCamera ডিফল্টরূপে অন্তত একটি ফ্রেম সমর্থন করে; আরো গ্রহণযোগ্য সঙ্গে.

যদি অনুরোধ করা বাফারকাউন্টটি সংযোজন করা না যায়, তাহলে ফাংশনটি BUFFER_NOT_AVAILABLE বা অন্যান্য প্রাসঙ্গিক ত্রুটি কোড প্রদান করে। এই ক্ষেত্রে, সিস্টেমটি পূর্বে সেট করা মান দিয়ে কাজ করতে থাকে।

startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);

এই ক্যামেরা থেকে EVS ক্যামেরা ফ্রেম ডেলিভারির অনুরোধ করে। IEvsCameraStream নতুন ইমেজ ফ্রেম সহ পর্যায়ক্রমিক কল পেতে শুরু করে যতক্ষণ না stopVideoStream() কল করা হয়। startVideoStream কলের 500ms এর মধ্যে ফ্রেমগুলি ডেলিভারি করা শুরু করতে হবে এবং শুরু করার পরে, ন্যূনতম 10 FPS এ তৈরি করতে হবে। ভিডিও স্ট্রিম শুরু করার জন্য প্রয়োজনীয় সময় কার্যকরভাবে যেকোন রিয়ারভিউ ক্যামেরা স্টার্টআপ সময়ের প্রয়োজনের বিপরীতে গণনা করা হয়। স্ট্রীম শুরু না হলে, একটি ত্রুটি কোড ফেরত দিতে হবে; অন্যথায় ঠিক আছে ফেরত দেওয়া হয়।

oneway doneWithFrame(BufferDesc buffer);

একটি ফ্রেম ফেরত দেয় যা IEvsCameraStream-এ বিতরণ করা হয়েছিল। IEvsCameraStream ইন্টারফেসে বিতরণ করা একটি ফ্রেম ব্যবহার করা হয়ে গেলে, পুনরায় ব্যবহারের জন্য ফ্রেমটি অবশ্যই IEvsCamera-এ ফেরত দিতে হবে। একটি ছোট, সীমিত সংখ্যক বাফার পাওয়া যায় (সম্ভবত একটির মতো ছোট), এবং যদি সরবরাহ শেষ হয়ে যায়, বাফার ফেরত না দেওয়া পর্যন্ত আর কোনও ফ্রেম বিতরণ করা হয় না, সম্ভাব্য ফলস্বরূপ ফ্রেমগুলি এড়িয়ে যায় (একটি নাল হ্যান্ডেল সহ একটি বাফার শেষ নির্দেশ করে একটি প্রবাহের এবং এই ফাংশনের মাধ্যমে ফেরত দেওয়ার প্রয়োজন নেই)। সাফল্যের উপর ঠিক আছে, বা INVALID_ARG বা BUFFER_NOT_AVAILABLE সহ সম্ভাব্য ত্রুটি কোড প্রদান করে।

stopVideoStream();

EVS ক্যামেরা ফ্রেমের ডেলিভারি বন্ধ করে দেয়। ডেলিভারি অ্যাসিঙ্ক্রোনাস হওয়ার কারণে, এই কল রিটার্ন করার পরে কিছু সময়ের জন্য ফ্রেমগুলি আসা চালিয়ে যেতে পারে৷ IEvsCameraStream-এ স্ট্রীম বন্ধ হওয়ার সংকেত না দেওয়া পর্যন্ত প্রতিটি ফ্রেম অবশ্যই ফেরত দিতে হবে। এমন একটি স্ট্রীমে stopVideoStream কল করা বৈধ যা ইতিমধ্যেই বন্ধ করা হয়েছে বা কখনও শুরু হয়নি, যে ক্ষেত্রে এটি উপেক্ষা করা হয়৷

getExtendedInfo(int32 opaqueIdentifier) generates (int32 value);

HAL বাস্তবায়ন থেকে ড্রাইভার-নির্দিষ্ট তথ্যের অনুরোধ করে। opaqueIdentifier জন্য অনুমোদিত মানগুলি ড্রাইভার-নির্দিষ্ট, তবে পাস করা কোনও মান ড্রাইভারকে ক্রাশ করতে পারে না। অচেনা opaqueIdentifier জন্য ড্রাইভারকে 0 দিতে হবে।

setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);

HAL বাস্তবায়নে একটি ড্রাইভার-নির্দিষ্ট মান পাঠায়। এই এক্সটেনশনটি শুধুমাত্র গাড়ি-নির্দিষ্ট এক্সটেনশনের সুবিধার্থে প্রদান করা হয়েছে এবং কোনো HAL বাস্তবায়নের জন্য এই কলটিকে ডিফল্ট অবস্থায় কাজ করার প্রয়োজন হবে না। ড্রাইভার যদি মান চিনে এবং গ্রহণ করে, ঠিক আছে ফেরত দিতে হবে; অন্যথায় INVALID_ARG বা অন্য প্রতিনিধি ত্রুটি কোড ফেরত দিতে হবে।

struct BufferDesc {
    uint32  width;      // Units of pixels
    uint32  height;     // Units of pixels
    uint32  stride;     // Units of pixels
    uint32  pixelSize;  // Size of single pixel in bytes
    uint32  format;     // May contain values from android_pixel_format_t
    uint32  usage;      // May contain values from Gralloc.h
    uint32  bufferId;   // Opaque value
    handle  memHandle;  // gralloc memory buffer handle
}

API এর মাধ্যমে পাস করা একটি চিত্র বর্ণনা করে। HAL ড্রাইভ ইমেজ বাফার বর্ণনা করার জন্য এই কাঠামোটি পূরণ করার জন্য দায়ী এবং HAL ক্লায়েন্টকে এই কাঠামোটিকে শুধুমাত্র-পঠন হিসাবে বিবেচনা করা উচিত। ক্ষেত্রগুলিতে ক্লায়েন্টকে একটি ANativeWindowBuffer অবজেক্ট পুনর্গঠন করার অনুমতি দেওয়ার জন্য যথেষ্ট তথ্য রয়েছে, যেমনটি EGL-এর সাথে eglCreateImageKHR() এক্সটেনশনের সাথে ইমেজ ব্যবহার করার প্রয়োজন হতে পারে।

  • width উপস্থাপিত ছবির পিক্সেলের প্রস্থ।
  • height উপস্থাপিত ছবির পিক্সেলে উচ্চতা।
  • stride প্রতিটি সারি পিক্সেলের সংখ্যা আসলে মেমরিতে দখল করে, সারিগুলির প্রান্তিককরণের জন্য যে কোনও প্যাডিংয়ের জন্য অ্যাকাউন্টিং। এর বাফার বর্ণনার জন্য gralloc দ্বারা গৃহীত কনভেনশনের সাথে মেলে পিক্সেলে প্রকাশ করা হয়েছে।
  • pixelSize । প্রতিটি পৃথক পিক্সেল দ্বারা দখলকৃত বাইটের সংখ্যা, চিত্রের সারিগুলির মধ্যে ধাপে ধাপের জন্য প্রয়োজনীয় বাইটে আকারের গণনা সক্ষম করে ( বাইটে stride = পিক্সেলে stride * pixelSize )।
  • format ছবির দ্বারা ব্যবহৃত পিক্সেল বিন্যাস। প্রদত্ত বিন্যাসটি প্ল্যাটফর্মের OpenGL বাস্তবায়নের সাথে সামঞ্জস্যপূর্ণ হতে হবে। সামঞ্জস্য পরীক্ষায় উত্তীর্ণ হতে, ক্যামেরা ব্যবহারের জন্য HAL_PIXEL_FORMAT_YCRCB_420_SP পছন্দ করা উচিত, এবং প্রদর্শনের জন্য RGBA বা BGRA পছন্দ করা উচিত।
  • usage HAL বাস্তবায়ন দ্বারা সেট করা ব্যবহারের পতাকা। HAL ক্লায়েন্টদের এই অপরিবর্তিত পাস করার আশা করা হচ্ছে (বিশদ বিবরণের জন্য, Gralloc.h সম্পর্কিত পতাকা দেখুন)।
  • bufferId HAL এপিআই-এর মাধ্যমে একটি রাউন্ড ট্রিপের পরে একটি বাফারকে স্বীকৃত করার অনুমতি দেওয়ার জন্য HAL বাস্তবায়ন দ্বারা নির্দিষ্ট করা একটি অনন্য মান। এই ক্ষেত্রে সঞ্চিত মানটি এইচএএল বাস্তবায়ন দ্বারা নির্বিচারে বেছে নেওয়া হতে পারে।
  • memHandle অন্তর্নিহিত মেমরি বাফারের জন্য হ্যান্ডেল যা চিত্রের ডেটা ধারণ করে। HAL বাস্তবায়ন এখানে একটি Gralloc বাফার হ্যান্ডেল সংরক্ষণ করতে বেছে নিতে পারে।

IEvsCameraStream

ক্লায়েন্ট অ্যাসিঙ্ক্রোনাস ভিডিও ফ্রেম ডেলিভারি পেতে এই ইন্টারফেসটি প্রয়োগ করে।

deliverFrame(BufferDesc buffer);

প্রতিবার একটি ভিডিও ফ্রেম পরিদর্শনের জন্য প্রস্তুত হলে HAL থেকে কলগুলি গ্রহণ করে৷ এই পদ্ধতিতে প্রাপ্ত বাফার হ্যান্ডেলগুলি অবশ্যই IEvsCamera::doneWithFrame() এ কলের মাধ্যমে ফেরত দিতে হবে। যখন IEvsCamera::stopVideoStream() এ একটি কল দিয়ে ভিডিও স্ট্রীম বন্ধ করা হয়, তখন পাইপলাইন নিষ্কাশনের সাথে সাথে এই কলব্যাক চলতে পারে৷ প্রতিটি ফ্রেম এখনও ফেরত দিতে হবে; যখন স্ট্রীমের শেষ ফ্রেমটি বিতরণ করা হয়, তখন একটি NULL bufferHandle বিতরণ করা হয়, যা স্ট্রিমের সমাপ্তি নির্দেশ করে এবং আর কোন ফ্রেম বিতরণ ঘটবে না। NULL bufferHandle নিজেই doneWithFrame() দিয়ে ফেরত পাঠানোর দরকার নেই, তবে অন্য সব হ্যান্ডেল অবশ্যই ফেরত দিতে হবে

যদিও মালিকানাধীন বাফার ফর্ম্যাটগুলি প্রযুক্তিগতভাবে সম্ভব, সামঞ্জস্য পরীক্ষার জন্য বাফারটি চারটি সমর্থিত ফর্ম্যাটের একটিতে থাকা প্রয়োজন: NV21 (YCrCb 4:2:0 সেমি-প্ল্যানার), YV12 (YCrCb 4:2:0 প্ল্যানার), YUYV (YCrCb 4: 2:2 ইন্টারলিভড), RGBA (32 বিট R:G:B:x), বিজিআরএ (৩২ বিট বি:জি:আর:এক্স)। প্ল্যাটফর্মের GLES বাস্তবায়নে নির্বাচিত বিন্যাসটি অবশ্যই একটি বৈধ GL টেক্সচার উত্স হতে হবে৷

অ্যাপটিকে bufferId ফিল্ড এবং BufferDesc কাঠামোর memHandle মধ্যে কোনো চিঠিপত্রের উপর নির্ভর করা উচিত নয়bufferId মানগুলি মূলত HAL ড্রাইভার বাস্তবায়নের জন্য ব্যক্তিগত, এবং এটি উপযুক্ত মনে করে সেগুলি ব্যবহার (এবং পুনরায় ব্যবহার) করতে পারে।

IEvs ডিসপ্লে

এই বস্তুটি Evs ডিসপ্লে উপস্থাপন করে, প্রদর্শনের অবস্থা নিয়ন্ত্রণ করে এবং চিত্রের প্রকৃত উপস্থাপনা পরিচালনা করে।

getDisplayInfo() generates (DisplayDesc info);

সিস্টেম দ্বারা প্রদত্ত EVS ডিসপ্লে সম্পর্কে প্রাথমিক তথ্য প্রদান করে ( DisplayDesc দেখুন)।

setDisplayState(DisplayState state) generates (EvsResult result);

প্রদর্শনের অবস্থা সেট করে। ক্লায়েন্টরা পছন্দসই অবস্থা প্রকাশ করার জন্য ডিসপ্লে অবস্থা সেট করতে পারে, এবং HAL বাস্তবায়নকে অবশ্যই অন্য যেকোনো রাজ্যে থাকাকালীন যেকোনো রাজ্যের জন্য একটি অনুরোধ অবশ্যই গ্রহণ করতে হবে, যদিও প্রতিক্রিয়াটি অনুরোধ উপেক্ষা করা হতে পারে।

আরম্ভ করার পরে, প্রদর্শনটি NOT_VISIBLE অবস্থায় শুরু হওয়ার জন্য সংজ্ঞায়িত করা হয়, যার পরে ক্লায়েন্ট VISIBLE_ON_NEXT_FRAME অবস্থার অনুরোধ করবে এবং ভিডিও সরবরাহ করা শুরু করবে বলে আশা করা হচ্ছে। যখন ডিসপ্লের আর প্রয়োজন হয় না, ক্লায়েন্ট শেষ ভিডিও ফ্রেম পাস করার পরে NOT_VISIBLE অবস্থার অনুরোধ করবে বলে আশা করা হয়।

যেকোনো সময় অনুরোধ করা যেকোনো রাজ্যের জন্য বৈধ। যদি ডিসপ্লেটি ইতিমধ্যেই দৃশ্যমান হয়, তাহলে VISIBLE_ON_NEXT_FRAME এ সেট করা থাকলে এটি দৃশ্যমান থাকবে। সবসময় ঠিক আছে রিটার্ন করে যদি না অনুরোধ করা স্টেটটি একটি অচেনা enum মান হয়, যে ক্ষেত্রে INVALID_ARG ফেরত দেওয়া হয়।

getDisplayState() generates (DisplayState state);

প্রদর্শন অবস্থা পায়। এইচএএল বাস্তবায়নের প্রকৃত বর্তমান অবস্থার রিপোর্ট করা উচিত, যা সাম্প্রতিক অনুরোধ করা অবস্থা থেকে ভিন্ন হতে পারে। ডিসপ্লে অবস্থা পরিবর্তনের জন্য দায়ী যুক্তিটি ডিভাইস স্তরের উপরে থাকা উচিত, এটি HAL বাস্তবায়নের জন্য স্বতঃস্ফূর্তভাবে প্রদর্শনের অবস্থা পরিবর্তন করা অবাঞ্ছিত করে তোলে।

getTargetBuffer() generates (handle bufferHandle);

প্রদর্শনের সাথে যুক্ত একটি ফ্রেম বাফারে একটি হ্যান্ডেল ফেরত দেয়। এই বাফারটি সফ্টওয়্যার এবং/অথবা GL দ্বারা লক করা এবং লেখা হতে পারে৷ ডিসপ্লেটি আর দৃশ্যমান না হলেও এই বাফারটি অবশ্যই returnTargetBufferForDisplay() এ একটি কল দিয়ে ফেরত দিতে হবে।

যদিও মালিকানাধীন বাফার ফর্ম্যাটগুলি প্রযুক্তিগতভাবে সম্ভব, সামঞ্জস্য পরীক্ষার জন্য বাফারটি চারটি সমর্থিত ফর্ম্যাটের একটিতে থাকা প্রয়োজন: NV21 (YCrCb 4:2:0 সেমি-প্ল্যানার), YV12 (YCrCb 4:2:0 প্ল্যানার), YUYV (YCrCb 4: 2:2 ইন্টারলিভড), RGBA (32 বিট R:G:B:x), বিজিআরএ (৩২ বিট বি:জি:আর:এক্স)। নির্বাচিত বিন্যাসটি প্ল্যাটফর্মের GLES বাস্তবায়নে একটি বৈধ GL রেন্ডার লক্ষ্য হতে হবে।

ত্রুটিতে, একটি নাল হ্যান্ডেল সহ একটি বাফার ফেরত দেওয়া হয়, কিন্তু এই ধরনের একটি বাফারকে returnTargetBufferForDisplay এ পাস করার প্রয়োজন নেই।

returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);

ডিসপ্লেকে বলে বাফার ডিসপ্লের জন্য প্রস্তুত। শুধুমাত্র getTargetBuffer() এ কলের মাধ্যমে পুনরুদ্ধার করা বাফারগুলি এই কলের সাথে ব্যবহারের জন্য বৈধ, এবং BufferDesc এর বিষয়বস্তু ক্লায়েন্ট অ্যাপ দ্বারা পরিবর্তিত নাও হতে পারে। এই কলের পরে, বাফারটি ক্লায়েন্টের দ্বারা ব্যবহারের জন্য আর বৈধ নয়। সাফল্যের উপর ঠিক আছে, বা INVALID_ARG বা BUFFER_NOT_AVAILABLE সহ সম্ভাব্য ত্রুটি কোড প্রদান করে।

struct DisplayDesc {
    string  display_id;
    int32   vendor_flags;  // Opaque value
}

একটি EVS প্রদর্শনের মৌলিক বৈশিষ্ট্য বর্ণনা করে এবং একটি EVS বাস্তবায়নের জন্য প্রয়োজনীয়। EVS ডিসপ্লে বর্ণনা করার জন্য এই কাঠামোটি পূরণ করার জন্য HAL দায়ী। একটি ফিজিক্যাল ডিসপ্লে বা ভার্চুয়াল ডিসপ্লে হতে পারে যা অন্য উপস্থাপনা ডিভাইসের সাথে ওভারলেড বা মিশ্রিত।

  • display_id । একটি স্ট্রিং যা ডিসপ্লেটিকে অনন্যভাবে সনাক্ত করে। এটি ডিভাইসের কার্নেল ডিভাইসের নাম বা ডিভাইসের জন্য একটি নাম হতে পারে, যেমন rearview । এই স্ট্রিংয়ের মানটি HAL বাস্তবায়ন দ্বারা নির্বাচিত হয় এবং উপরের স্ট্যাকের দ্বারা অস্বচ্ছভাবে ব্যবহৃত হয়।
  • vendor_flags ড্রাইভার থেকে একটি কাস্টম EVS অ্যাপে অস্বচ্ছভাবে বিশেষ ক্যামেরা তথ্য পাস করার একটি পদ্ধতি। এটি ড্রাইভার থেকে EVS অ্যাপ পর্যন্ত অব্যক্ত করা হয়, যা এটিকে উপেক্ষা করার জন্য বিনামূল্যে।
enum DisplayState : uint32 {
    NOT_OPEN,               // Display has not been opened yet
    NOT_VISIBLE,            // Display is inhibited
    VISIBLE_ON_NEXT_FRAME,  // Will become visible with next frame
    VISIBLE,                // Display is currently active
    DEAD,                   // Display is not available. Interface should be closed
}

ইভিএস ডিসপ্লের অবস্থা বর্ণনা করে, যা নিষ্ক্রিয় করা যেতে পারে (ড্রাইভারের কাছে দৃশ্যমান নয়) বা সক্ষম (ড্রাইভারকে একটি ছবি দেখানো)। একটি ক্ষণস্থায়ী অবস্থা অন্তর্ভুক্ত করে যেখানে ডিসপ্লেটি এখনও দৃশ্যমান নয় কিন্তু returnTargetBufferForDisplay() কলের মাধ্যমে চিত্রের পরবর্তী ফ্রেমের বিতরণের সাথে দৃশ্যমান হওয়ার জন্য প্রস্তুত।

ইভিএস ম্যানেজার

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

EVS ম্যানেজার অন্তর্নিহিত HAL ড্রাইভারের মতো একই API প্রয়োগ করে এবং একাধিক সমসাময়িক ক্লায়েন্টকে সমর্থন করে প্রসারিত পরিষেবা প্রদান করে (একাধিক ক্লায়েন্ট ইভিএস ম্যানেজারের মাধ্যমে একটি ক্যামেরা খুলতে পারে এবং একটি ভিডিও স্ট্রিম গ্রহণ করতে পারে)।

ইভিএস ম্যানেজার ও EVS হার্ডওয়্যার API ডায়াগ্রাম।
চিত্র 2. ইভিএস ম্যানেজার EVS হার্ডওয়্যার API এর অন্তর্নিহিত আয়না।

EVS হার্ডওয়্যার HAL ইমপ্লিমেন্টেশন বা EVS Manager API-এর মাধ্যমে কাজ করার সময় অ্যাপগুলি কোনও পার্থক্য দেখতে পায় না শুধুমাত্র EVS Manager API সমসাময়িক ক্যামেরা স্ট্রিম অ্যাক্সেসের অনুমতি দেয়। EVS ম্যানেজার নিজেই, EVS হার্ডওয়্যার HAL স্তরের একজন অনুমোদিত ক্লায়েন্ট, এবং EVS হার্ডওয়্যার HAL-এর জন্য প্রক্সি হিসেবে কাজ করে।

নিম্নলিখিত বিভাগগুলি শুধুমাত্র সেই সমস্ত কলগুলিকে বর্ণনা করে যেগুলির EVS ম্যানেজার বাস্তবায়নে ভিন্ন (বর্ধিত) আচরণ রয়েছে; অবশিষ্ট কল EVS HAL বর্ণনার সাথে অভিন্ন।

IEvs গণনাকারী

openCamera(string camera_id) generates (IEvsCamera camera);

অনন্য camera_id স্ট্রিং দ্বারা চিহ্নিত একটি নির্দিষ্ট ক্যামেরার সাথে ইন্টারঅ্যাক্ট করতে ব্যবহৃত একটি ইন্টারফেস অবজেক্ট পায়। ব্যর্থ হলে একটি NULL প্রদান করে। EVS ম্যানেজার লেয়ারে, যতক্ষণ পর্যাপ্ত সিস্টেম রিসোর্স পাওয়া যায়, ইতিমধ্যেই খোলা একটি ক্যামেরা অন্য একটি প্রক্রিয়ার মাধ্যমে আবার খোলা হতে পারে, যা একাধিক ভোক্তা অ্যাপে ভিডিও স্ট্রিম টিইং করার অনুমতি দেয়। EVS ম্যানেজার স্তরের camera_id স্ট্রিংগুলি EVS হার্ডওয়্যার স্তরে রিপোর্ট করা একই রকম৷

আইইভিএস ক্যামেরা

EVS ম্যানেজার প্রদত্ত IEvsCamera বাস্তবায়ন অভ্যন্তরীণভাবে ভার্চুয়ালাইজ করা হয়েছে যাতে একজন ক্লায়েন্টের দ্বারা একটি ক্যামেরার অপারেশন অন্য ক্লায়েন্টদের প্রভাবিত করে না, যা তাদের ক্যামেরাগুলিতে স্বাধীন অ্যাক্সেস বজায় রাখে।

startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);

ভিডিও স্ট্রিম শুরু হয়। ক্লায়েন্টরা স্বাধীনভাবে একই অন্তর্নিহিত ক্যামেরায় ভিডিও স্ট্রীম শুরু এবং বন্ধ করতে পারে। প্রথম ক্লায়েন্ট শুরু হলে অন্তর্নিহিত ক্যামেরা শুরু হয়।

doneWithFrame(uint32 frameId, handle bufferHandle) generates (EvsResult result);

একটি ফ্রেম ফেরত দেয়। প্রতিটি ক্লায়েন্টকে তাদের ফ্রেমগুলি ফেরত দিতে হবে যখন সেগুলি সম্পন্ন হবে, তবে যতক্ষণ তারা ইচ্ছা ততক্ষণ তাদের ফ্রেমগুলি ধরে রাখার অনুমতি দেওয়া হয়েছে। যখন একটি ক্লায়েন্ট দ্বারা রাখা ফ্রেম গণনা তার কনফিগার করা সীমায় পৌঁছে যায়, তখন এটি একটি ফেরত না দেওয়া পর্যন্ত এটি আর কোনও ফ্রেম পাবে না। এই ফ্রেম স্কিপিং অন্য ক্লায়েন্টদের প্রভাবিত করে না, যারা প্রত্যাশিতভাবে সমস্ত ফ্রেম পেতে থাকে।

stopVideoStream();

একটি ভিডিও স্ট্রিম বন্ধ করে। প্রতিটি ক্লায়েন্ট অন্য ক্লায়েন্টদের প্রভাবিত না করে যেকোনো সময় তার ভিডিও স্ট্রিম বন্ধ করতে পারে। হার্ডওয়্যার স্তরের অন্তর্নিহিত ক্যামেরা স্ট্রীম বন্ধ হয়ে যায় যখন একটি প্রদত্ত ক্যামেরার শেষ ক্লায়েন্ট তার স্ট্রিম বন্ধ করে দেয়।

setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);

একটি ড্রাইভার-নির্দিষ্ট মান পাঠায়, সম্ভাব্যভাবে একটি ক্লায়েন্টকে অন্য ক্লায়েন্টকে প্রভাবিত করতে সক্ষম করে। যেহেতু EVS ম্যানেজার বিক্রেতা-সংজ্ঞায়িত নিয়ন্ত্রণ শব্দগুলির প্রভাব বুঝতে পারে না, সেগুলি ভার্চুয়ালাইজ করা হয় না এবং কোনও পার্শ্ব প্রতিক্রিয়া একটি প্রদত্ত ক্যামেরার সমস্ত ক্লায়েন্টের জন্য প্রযোজ্য। উদাহরণস্বরূপ, যদি একজন বিক্রেতা ফ্রেম রেট পরিবর্তন করতে এই কলটি ব্যবহার করেন, তবে প্রভাবিত হার্ডওয়্যার স্তর ক্যামেরার সমস্ত ক্লায়েন্ট নতুন হারে ফ্রেম গ্রহণ করবে।

IEvs ডিসপ্লে

ডিসপ্লের শুধুমাত্র একজন মালিককে অনুমতি দেওয়া হয়, এমনকি EVS ম্যানেজার লেভেলেও। ম্যানেজার কোন কার্যকারিতা যোগ করে না এবং IEvsDisplay ইন্টারফেসকে সরাসরি অন্তর্নিহিত HAL বাস্তবায়নের মাধ্যমে পাস করে।

ইভিএস অ্যাপ

অ্যান্ড্রয়েডে রয়েছে একটি EVS অ্যাপের একটি নেটিভ C++ রেফারেন্স বাস্তবায়ন যা ইভিএস ম্যানেজার এবং যানবাহন HAL-এর সাথে প্রাথমিক রিয়ারভিউ ক্যামেরা ফাংশন প্রদানের জন্য যোগাযোগ করে। অ্যাপটি সিস্টেম বুট প্রক্রিয়ার খুব তাড়াতাড়ি শুরু হবে বলে আশা করা হচ্ছে, উপলব্ধ ক্যামেরা এবং গাড়ির অবস্থা (গিয়ার এবং টার্ন সিগন্যাল স্টেট) এর উপর নির্ভর করে উপযুক্ত ভিডিও দেখানো হবে। OEMs তাদের নিজস্ব গাড়ি-নির্দিষ্ট যুক্তি এবং উপস্থাপনা দিয়ে EVS অ্যাপ পরিবর্তন বা প্রতিস্থাপন করতে পারে।

চিত্র 3. ইভিএস অ্যাপের নমুনা যুক্তি, ক্যামেরা তালিকা পান।


চিত্র 4. ইভিএস অ্যাপের নমুনা যুক্তি, ফ্রেম কলব্যাক গ্রহণ করুন।

যেহেতু ইমেজ ডেটা একটি স্ট্যান্ডার্ড গ্রাফিক্স বাফারে অ্যাপে উপস্থাপিত হয়, তাই অ্যাপটি সোর্স বাফার থেকে আউটপুট বাফারে ছবি সরানোর জন্য দায়ী। যদিও এটি একটি ডেটা কপির খরচ প্রবর্তন করে, এটি অ্যাপটিকে এটির ইচ্ছামত যে কোনও ফ্যাশনে ডিসপ্লে বাফারে চিত্রটি রেন্ডার করার সুযোগও দেয়।

উদাহরণস্বরূপ, অ্যাপটি সম্ভবত একটি ইনলাইন স্কেল বা ঘূর্ণন ক্রিয়াকলাপের সাথে পিক্সেল ডেটা নিজেই সরানো বেছে নিতে পারে। অ্যাপটি একটি ওপেনজিএল টেক্সচার হিসাবে উত্স চিত্রটি ব্যবহার করতে এবং আইকন, নির্দেশিকা এবং অ্যানিমেশনের মতো ভার্চুয়াল উপাদান সহ আউটপুট বাফারে একটি জটিল দৃশ্য রেন্ডার করতে পারে। একটি আরও পরিশীলিত অ্যাপ একাধিক সমসাময়িক ইনপুট ক্যামেরা নির্বাচন করতে পারে এবং সেগুলিকে একক আউটপুট ফ্রেমে একত্রিত করতে পারে (যেমন টপ-ডাউন, গাড়ির আশেপাশের ভার্চুয়াল ভিউতে ব্যবহারের জন্য)।

EVS ডিসপ্লে HAL-এ EGL/SurfaceFlinger ব্যবহার করুন

Android 10-এ EVS ডিসপ্লে HAL ইমপ্লিমেন্টেশন রেন্ডার করতে EGL কীভাবে ব্যবহার করবেন এই বিভাগটি ব্যাখ্যা করে।

একটি EVS HAL রেফারেন্স বাস্তবায়ন EGL ব্যবহার করে স্ক্রীনে ক্যামেরা প্রিভিউ রেন্ডার করতে এবং টার্গেট EGL রেন্ডার পৃষ্ঠ তৈরি করতে libgui ব্যবহার করে। অ্যান্ড্রয়েড 8 (এবং উচ্চতর), libgui VNDK-private হিসাবে শ্রেণীবদ্ধ করা হয়েছে, যা VNDK লাইব্রেরিতে উপলব্ধ লাইব্রেরির একটি গ্রুপকে বোঝায় যা বিক্রেতা প্রক্রিয়াগুলি ব্যবহার করতে পারে না। যেহেতু HAL বাস্তবায়নকে অবশ্যই ভেন্ডর পার্টিশনে থাকতে হবে, বিক্রেতাদের HAL বাস্তবায়নে সারফেস ব্যবহার করতে বাধা দেওয়া হয়।

বিক্রেতা প্রক্রিয়ার জন্য libgui তৈরি করা

EVS ডিসপ্লে HAL বাস্তবায়নে EGL/SurfaceFlinger ব্যবহার করার একমাত্র বিকল্প হিসেবে libgui এর ব্যবহার কাজ করে। বিল্ড স্ক্রিপ্টে অতিরিক্ত বিল্ড টার্গেট ব্যবহার করে সরাসরি ফ্রেমওয়ার্ক/নেটিভ/লিবস/গুই-এর মাধ্যমে libgui বাস্তবায়নের সবচেয়ে সহজ উপায়। দুটি ক্ষেত্র যোগ করা ছাড়া এই লক্ষ্যটি libgui টার্গেটের মতোই ঠিক:

  • name
  • vendor_available
cc_library_shared {
    name: "libgui_vendor",
    vendor_available: true,
    vndk: {
        enabled: false,
    },
    double_loadable: true,

defaults: ["libgui_bufferqueue-defaults"],
srcs: [ // bufferhub is not used when building libgui for vendors target: { vendor: { cflags: [ "-DNO_BUFFERHUB", "-DNO_INPUT", ],

দ্রষ্টব্য: বিক্রেতা লক্ষ্যগুলি NO_INPUT ম্যাক্রো দিয়ে তৈরি করা হয়েছে, যা পার্সেল ডেটা থেকে একটি 32-বিট শব্দ সরিয়ে দেয়৷ যেহেতু SurfaceFlinger আশা করে যে এই ক্ষেত্রটি সরানো হয়েছে, SurfaceFlinger পার্সেলটি পার্স করতে ব্যর্থ হয়েছে৷ এটি একটি fcntl ব্যর্থতা হিসাবে পরিলক্ষিত হয়:

W Parcel  : Attempt to read object from Parcel 0x78d9cffad8 at offset 428 that is not in the object list
E Parcel  : fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is 0, fd_count is 20, error: Unknown error 2147483647
W Parcel  : Attempt to read object from Parcel 0x78d9cffad8 at offset 544 that is not in the object list

এই অবস্থার সমাধান করতে:

diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 6066421fa..25cf5f0ce 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -54,6 +54,9 @@ status_t layer_state_t::write(Parcel& output) const
    output.writeFloat(color.b);
#ifndef NO_INPUT
    inputInfo.write(output);
+#else
+    // Write a dummy 32-bit word.
+    output.writeInt32(0);
#endif
    output.write(transparentRegion);
    output.writeUint32(transform);

নমুনা নির্মাণ নির্দেশাবলী নীচে প্রদান করা হয়. একটি $(ANDROID_PRODUCT_OUT)/system/lib64/libgui_vendor.so পাওয়ার প্রত্যাশা করুন।

$ cd <your_android_source_tree_top>
$ . ./build/envsetup.
$ lunch <product_name>-<build_variant>
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=10
TARGET_PRODUCT=<product_name>
TARGET_BUILD_VARIANT=<build_variant>
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a9
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=<host_linux_version>
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=QT
OUT_DIR=out
============================================

$ m -j libgui_vendor … $ find $ANDROID_PRODUCT_OUT/system -name "libgui_vendor*" .../out/target/product/hawk/system/lib64/libgui_vendor.so .../out/target/product/hawk/system/lib/libgui_vendor.so

EVS HAL বাস্তবায়নে বাইন্ডার ব্যবহার করুন

অ্যান্ড্রয়েড 8 (এবং উচ্চতর) এ, /dev/binder ডিভাইস নোডটি ফ্রেমওয়ার্ক প্রক্রিয়াগুলির জন্য একচেটিয়া হয়ে উঠেছে এবং তাই, বিক্রেতা প্রক্রিয়াগুলির কাছে অ্যাক্সেসযোগ্য নয়। পরিবর্তে, বিক্রেতা প্রক্রিয়াগুলিকে /dev/hwbinder ব্যবহার করা উচিত এবং যেকোন AIDL ইন্টারফেসকে HIDL-এ রূপান্তর করতে হবে। যারা ভেন্ডর প্রক্রিয়ার মধ্যে AIDL ইন্টারফেস ব্যবহার চালিয়ে যেতে চান তাদের জন্য বাইন্ডার ডোমেন, /dev/vndbinder ব্যবহার করুন।

IPC ডোমেইন বর্ণনা
/dev/binder AIDL ইন্টারফেস সহ ফ্রেমওয়ার্ক/অ্যাপ প্রক্রিয়াগুলির মধ্যে IPC
/dev/hwbinder HIDL ইন্টারফেস সহ ফ্রেমওয়ার্ক/বিক্রেতা প্রক্রিয়াগুলির মধ্যে IPC
HIDL ইন্টারফেস সহ বিক্রেতা প্রক্রিয়াগুলির মধ্যে IPC
/dev/vndbinder AIDL ইন্টারফেস সহ বিক্রেতা/বিক্রেতার প্রক্রিয়াগুলির মধ্যে IPC

SurfaceFlinger AIDL ইন্টারফেসগুলিকে সংজ্ঞায়িত করার সময়, বিক্রেতা প্রক্রিয়াগুলি ফ্রেমওয়ার্ক প্রক্রিয়াগুলির সাথে যোগাযোগ করার জন্য শুধুমাত্র HIDL ইন্টারফেসগুলি ব্যবহার করতে পারে৷ বিদ্যমান এআইডিএল ইন্টারফেসকে এইচআইডিএল-এ রূপান্তর করার জন্য একটি অ-তুচ্ছ পরিমাণ কাজ প্রয়োজন। সৌভাগ্যবশত, অ্যান্ড্রয়েড এমন একটি পদ্ধতি প্রদান করে যার সাহায্যে libbinder এর জন্য বাইন্ডার ড্রাইভার নির্বাচন করা যায়, যার সাথে ইউজারস্পেস লাইব্রেরি প্রসেস সংযুক্ত থাকে।

diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp
index d8fb3166..5fd02935 100644
--- a/evs/sampleDriver/service.cpp
+++ b/evs/sampleDriver/service.cpp
@@ -21,6 +21,7 @@
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include <utils/Log.h>
+#include <binder/ProcessState.h>

#include "ServiceNames.h"
#include "EvsEnumerator.h"
@@ -43,6 +44,9 @@ using namespace android;
int main() {
    ALOGI("EVS Hardware Enumerator service is starting");


+    // Use /dev/binder for SurfaceFlinger
+    ProcessState::initWithDriver("/dev/binder");
+


    // Start a thread to listen to video device addition events.
    std::atomic<bool> running { true };
    std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));

দ্রষ্টব্য: Process বা IPCThreadState এ কল করার আগে বা কোনো বাইন্ডার কল করার আগে ভেন্ডর প্রসেসগুলিকে এটি কল করা উচিত।

SELinux নীতি

যদি ডিভাইস বাস্তবায়ন সম্পূর্ণ তিনগুণ হয়, SELinux বিক্রেতা প্রক্রিয়াগুলিকে /dev/binder ব্যবহার করা থেকে বাধা দেয়। উদাহরণস্বরূপ, একটি EVS HAL নমুনা বাস্তবায়ন hal_evs_driver ডোমেনে বরাদ্দ করা হয়েছে এবং binder_device ডোমেনে r/w অনুমতি প্রয়োজন।

W ProcessState: Opening '/dev/binder' failed: Permission denied
F ProcessState: Binder driver could not be opened. Terminating.
F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 9145 (android.hardwar), pid 9145 (android.hardwar)
W android.hardwar: type=1400 audit(0.0:974): avc: denied { read write } for name="binder" dev="tmpfs" ino=2208 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:binder_device:s0 tclass=chr_file permissive=0

যাইহোক, এই অনুমতিগুলি যোগ করা একটি বিল্ড ব্যর্থতার কারণ হয়ে দাঁড়ায় কারণ এটি একটি ফুল-ট্রেবল ডিভাইসের জন্য system/sepolicy/domain.te তে সংজ্ঞায়িত নিম্নলিখিত কখনই অনুমতি না দেওয়া নিয়মগুলি লঙ্ঘন করে৷

libsepol.report_failure: neverallow on line 631 of system/sepolicy/public/domain.te (or line 12436 of policy.conf) violated by allow hal_evs_driver binder_device:chr_file { read write };
libsepol.check_assertions: 1 neverallow failures occurred
full_treble_only(`
neverallow {
    domain
    -coredomain
    -appdomain
    -binder_in_vendor_violators
} binder_device:chr_file rw_file_perms;
')

binder_in_vendor_violators হল একটি বাগ ধরতে এবং বিকাশের নির্দেশিকা প্রদানের জন্য একটি বৈশিষ্ট্য। উপরে বর্ণিত Android 10 লঙ্ঘন সমাধান করতেও এটি ব্যবহার করা যেতে পারে।

diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te
index f1f31e9fc..6ee67d88e 100644
--- a/evs/sepolicy/evs_driver.te
+++ b/evs/sepolicy/evs_driver.te
@@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain;
hal_server_domain(hal_evs_driver, hal_evs)
hal_client_domain(hal_evs_driver, hal_evs)

+# Allow to use /dev/binder
+typeattribute hal_evs_driver binder_in_vendor_violators;
+
# allow init to launch processes in this context
type hal_evs_driver_exec, exec_type, file_type, system_file_type;
init_daemon_domain(hal_evs_driver)

বিক্রেতা প্রক্রিয়া হিসাবে EVS HAL রেফারেন্স বাস্তবায়ন তৈরি করুন

একটি রেফারেন্স হিসাবে, আপনি নিম্নলিখিত পরিবর্তনগুলি packages/services/Car/evs/Android.mk এ প্রয়োগ করতে পারেন। সমস্ত বর্ণিত পরিবর্তনগুলি আপনার বাস্তবায়নের জন্য কাজ করে তা নিশ্চিত করতে ভুলবেন না।

diff --git a/evs/sampleDriver/Android.mk b/evs/sampleDriver/Android.mk
index 734feea7d..0d257214d 100644
--- a/evs/sampleDriver/Android.mk
+++ b/evs/sampleDriver/Android.mk
@@ -16,7 +16,7 @@ LOCAL_SRC_FILES := \
LOCAL_SHARED_LIBRARIES := \
    android.hardware.automotive.evs@1.0 \
    libui \
-    libgui \
+    libgui_vendor \
    libEGL \
    libGLESv2 \
    libbase \
@@ -33,6 +33,7 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-sample.rc

LOCAL_MODULE := android.hardware.automotive.evs@1.0-sample
+LOCAL_PROPRIETARY_MODULE := true

LOCAL_MODULE_TAGS := optional
LOCAL_STRIP_MODULE := keep_symbols
@@ -40,6 +41,7 @@ LOCAL_STRIP_MODULE := keep_symbols
LOCAL_CFLAGS += -DLOG_TAG=\"EvsSampleDriver\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+LOCAL_CFLAGS += -Iframeworks/native/include

#NOTE:  It can be helpful, while debugging, to disable optimizations
#LOCAL_CFLAGS += -O0 -g
diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp
index d8fb31669..5fd029358 100644
--- a/evs/sampleDriver/service.cpp
+++ b/evs/sampleDriver/service.cpp
@@ -21,6 +21,7 @@
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include <utils/Log.h>
+#include <binder/ProcessState.h>

#include "ServiceNames.h"
#include "EvsEnumerator.h"
@@ -43,6 +44,9 @@ using namespace android;
int main() {
    ALOGI("EVS Hardware Enumerator service is starting");
+    // Use /dev/binder for SurfaceFlinger
+    ProcessState::initWithDriver("/dev/binder");
+
     // Start a thread to listen video device addition events.
    std::atomic<bool> running { true };
    std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));
diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te
index f1f31e9fc..632fc7337 100644
--- a/evs/sepolicy/evs_driver.te
+++ b/evs/sepolicy/evs_driver.te
@@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain;
hal_server_domain(hal_evs_driver, hal_evs)
hal_client_domain(hal_evs_driver, hal_evs)

+# allow to use /dev/binder
+typeattribute hal_evs_driver binder_in_vendor_violators;
+
# allow init to launch processes in this context
type hal_evs_driver_exec, exec_type, file_type, system_file_type;
init_daemon_domain(hal_evs_driver)
@@ -22,3 +25,7 @@ allow hal_evs_driver ion_device:chr_file r_file_perms;

# Allow the driver to access kobject uevents
allow hal_evs_driver self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl;
+
+# Allow the driver to use the binder device
+allow hal_evs_driver binder_device:chr_file rw_file_perms;