কল্পনা করুন: আপনি একটি ক্যাফেতে বসে আছেন, ল্যাপটপ খোলা, ফোন টেবিলে, স্মার্টওয়াচ প্রতি মিনিটে বাজছে, এবং ব্লুটুথ ইয়ারবাডসে গান বাজছে। আপনার দৃষ্টিতে সব শান্ত। কিন্তু আপনার ফোন দৃষ্টিতে, এটি folyamendraরূপে অগণিত ছোট ব্লুটুথ প্যাকেট জাগল করছে।
প্রতিবার আপনার ঘড়ি ধাপ সিঙ্ক করলে, প্রতিবার আপনার ইয়ারবাডস অডিও চান্ক পায়, প্রতিবার একটি ব্যাকগ্রাউন্ড ডিভাইস চেক-ইন করলে – আপনার ফোনের মূল অ্যাপ্লিকেশন প্রসেসর বাধ্য হয়ে উঠে, ডেটা দেখে, সেটা কী করতে হবে সেটা تصمیم নেয়, এবং আবার ঘুমিয়ে পড়ে। একই কাজ হাজার হাজার বার করলে, সেটা ৫০০০ mAh ব্যাটারিও ক্ষুদ্র লাগতে শুরু করে।
Android ইঞ্জিনিয়াররা এই প্যাটার্নটি দেখে মূলত বলল, "কি হয় যদি আমরা প্রতিটি ছোট ব্লুটুথ জিনিসের জন্য বড় CPUকে জাগিয়ে না থাকি? কি হয় যদি আমাদের একটি ছোট হেল্পার ব্রেন থাকে যার একমাত্র কাজ হলো উবো রিপিটেটিভ ব্লুটুথ ট্রাফিক হ্যান্ডেল করা যতক্ষণ মেইন CPU রিল্যাক্স করে?" সেটিই হলো লো পাওয়ার আইল্যান্ড বা সংক্ষেপে LPI কনসেপ্টের উৎপত্তি।
আধুনিক Android ব্লুটুথ আর্কিটেকচারে, বিশেষ করে AOSP 16 জেনারেশন থেকে, ব্লুটুথের ভালো جزءًا একটি ডেডিকেটেড লো পাওয়ার প্রসেসরের तरफ অফলোড করা যায় যা ব্লুটুথ রেডিওর কাছাকাছি থাকে। এই ছোট প্রসেসর ব্লুটুথ কন্ট্রোলার বা SoC-তে এম্বেডেড থাকে এবং খুব কার্যকরভাবে চলতে ডিজাইন করা হয়েছে। এটি মেইন CPU-এর চেয়ে অনেক কম পাওয়ার খরচ করে এবং ফুল অ্যাপ্লিকেশন প্রসেসরের মত ব্যাটারি ড্রেইন না করেই জেগে থাকতে পারে। Android-এর কাজ হলো ডিসাইড করা কোন ট্রাফিক এই আইল্যান্ডে থাকতে পারে এবং কোন ট্রাফিক এখনও মেইন CPU-তে লাগবে।
কিন্তু Android এই সিদ্ধান্ত প্র্যাকটিক্যালি কীভাবে নেয়? ইহায় ব্লুটুথ সকেট এবং কিছু ব্লুটুথসকেটসেটিংস (BluetoothSocketSettings) আসে।
একটি সাধারণ অ্যাপে, যখন আপনি একটি BluetoothSocket খুলেন, তখন লাগে আপনি শুধু একটি পাইপ খুলছেন যাতে বাইট পাঠানো ও রিসিভ করা যায়। আন্ডার দ্য হুড কিন্তু, ফ্রেমওয়ার্ক একটি অনেক গভীর প্রশ্ন করছে: এই পাইপটি কি বড় হাইওয়ের মাধ্যমে যাবে যা মেইন CPUকে জাগিয়ে দেবে, নাকি এই পাইপটি সরাসরি লো পাওয়ার আইল্যান্ডের প্রাইভেট রোড নেটওয়ার্কের সাথে কানেক্টেড হতে পারে?
লেটেস্ট AOSP ব্লুটুথ স্ট্যাকে, এই প্রশ্নের উত্তর একটি ছোট কনফিগারেশন অবজেক্টের মাধ্যমে এক্সপ্রেস করা হয়: BluetoothSocketSettings। এই ক্লাস সিস্টেম লেভেল কোডকে অনুমতি দেয় একটি সকেট কীভাবে বিয়হেভ করবে সেটা বর্ণনা করার জন্য। এটি স্পেসিফাই করতে পারে যে ডেটাটি নর্মাল হোস্ট পাথেই থাকবে নাকি হার্ডওয়ার ডেটা পাথের মাধ্যমে অফলোড হবে যা লো পাওয়ার প্রসেসরে শেষ হবে।
এর ভেতরে DATA_PATH_NO_OFFLOAD এবং DATA_PATH_HARDWARE_OFFLOAD মতো ফিল্ড রয়েছে, প্লাস অতিরিক্ত ইনফরমেশন যেন hubId, endpointId, এবং requestedMaximumPacketSize যা কন্ট্রোলারকে বুঝাতে সাহায্য করে LPI ওয়ার্ল্ডে প্যাকেট কীভাবে রাউট করতে হবে।
বাহ্যিক দৃষ্টিতে, এটি এখনও একটি নরমাল BluetoothSocket এর মত দেখাবে। কিন্তু ব্লুটুথ ফ্রেমওয়ার্কের ভেতরে, সেই সকেটটি এখন এক্সট্রা মেটাডেটা সহ ট্যাগ করা থাকছে যা চুপচাপ ব্লুটুথ স্ট্যাককে বলে: "এইটা স্পেশাল, এটাকে আইল্যান্ডে পাঠাও।"
হোস্ট স্ট্যাক তারপর ব্লুটুথ সিস্টেমের একটি নতুন লেয়ারের সাথে কথা বলে যেটা হলো LPP অফলোড ম্যানেজার এবং একটি সকেট-স্পেসিফিক HAL (Hardware Abstraction Layer) যাতে লো পাওয়ার প্রসেসরকে জানানো যায় যতক্ষণ একটি সকেট খুলা বা বন্ধ হয়, এবং সেটা ডেটা হ্যান্ডেল করার দায়িত্ব নিতে পারে।
সুতরাং, যদি আমরা ক্যাফেAnalogy টি রাখি, তবে আগে প্রতিটি ব্লুটুথ কাস্টমার সরাসরি মেইন বারিস্টার চিৎকার করত। লো পাওয়ার আইল্যান্ড এবং BluetoothSocketSettings-এর সাথে, Android বলতে পারে, "এই রেগুলার এসপ্রেসো অর্ডারগুলো সাইড কাউন্টারের জুনিয়র বারিস্টার দিয়ে যেতে পারে। শুধু ਵির্ড কাস্টম ড্রিংকগুলো মেইন বারিস্টার কাছে যাবে।" ইউজারের জন্য একই ব্লুটুথ অভিজ্ঞতা, কিন্তু কাউন্টারের পেছনে অনেক কম কئос এবং বর্জিত শক্তি।
এই আর্টিকেলে, আমরা এই হাই-লেভেল গল্প থেকে আসলে Android APIs-এ জুম ইন করব। আমরা দেখব কীভাবে BluetoothSocketSettings ফ্রেমওয়ার্কে ডিফাইন করা হয়, কীভাবে হার্ডওয়ার অফলোড রিকোয়েস্ট করা হয়, এবং hubId এবং endpointId처럼 যে ভয়ংকর ফিল্ডগুলো আসলে সাদা ইংরেজিতে কী মানে।
সূচিপত্র
BluetoothSocketSettings-এর анатомি
HAL-এর ভেতর: ব্লুটুথ অফলোড আসলে কীভাবে কাজ করে
CPU ঘুমিয়ে থাকলে কিন্তু ব্লুটুথ জেগে থাকে: পাওয়ার ম্যানেজমেন্ট একশনে
ডেভেলপাররা কীভাবে BluetoothSocketSettings ব্যবহার করতে পারে
শেষ অধ্যায়: স্মার্টলি ঘুমানোর এলেগ্যান্স
BluetoothSocketSettings-এর Анатомি
আমরা এতক্ষণ BluetoothSocketSettings কে যেন কয়েকটি ম্যাজিক্যাল টিকেট বলে বলছিলাম যা আপনার প্যাকেটগুলোকে আপনার ফোনের ভেতর কোথাও একটি সান্নি লো-পাওয়ার আইল্যান্ডে পাঠিয়ে দেয়। এখন আসলে সেটি কোডে কেমন দেখে সেটা দেখা যাক।
আপনি যদি Android Open Source Project ট্রি খুলেন এবং ফ্রেমওয়ার্ক লেয়ারে নেভিগেট করেন, তবে একটি ক্লাস ডেফিনেশন পাবেন frameworks/base/core/java/android/bluetooth/BluetoothSocketSettings.java অধীনে। প্রথম নজরে এটি ছোট দেখাবে, প্রায় অনেক সরল যেটা ততটুকু ব্যাটারি বাঁচায়। কিন্তু এই ছোট ক্লাসটি সিক্রেট ইনস্ট্রাকশন বহন করে যা ব্লুটুথ স্ট্যাককে বলে আপনার সকেটের ডেটা কোথায় ফ্লো করবে।
এখানে একটি স্ট্রিপ-ডাউন ভার্সন দেওয়া হলো:
public final class BluetoothSocketSettings implements Parcelable { public static final int DATA_PATH_NO_OFFLOAD = 0; public static final int DATA_PATH_HARDWARE_OFFLOAD = 1; private int mDataPath; private int mHubId; private int mEndpointId; private int mRequestedMaxPacketSize; public BluetoothSocketSettings(int dataPath, int hubId, int endpointId, int requestedMaxPacketSize) { mDataPath = dataPath; mHubId = hubId; mEndpointId = endpointId; mRequestedMaxPacketSize = requestedMaxPacketSize; } public int getDataPath() { return mDataPath; } public int getHubId() { return mHubId; } public int getEndpointId() { return mEndpointId; } public int getRequestedMaxPacketSize() { return mRequestedMaxPacketSize; } } Android ব্লুটুথে যখন একটি নতুন সকেট তৈরি হয়, সিস্টেম বা প্রিভিলেজড সার্ভিস এই সেটিংস অবজেক্টটি স্ট্যাকে পাস করে নিচে। কী লাইনটি হলো DATA_PATH_HARDWARE_OFFLOAD। সেটিই সইচ যা ব্লুটুথ সিস্টেমকে বলে, "হে, এই ট্রাফিককে কন্ট্রোলারের মাইক্রোপ্রসেসরে রাখার চেষ্টা করো মেইন CPUকে জাগিয়ে না।"
hubId এবং endpointId হলো আইল্যান্ডের অ্যাড্রেস। সেগুলো ফার্মওয়ারকে বলে কোন লজিক্যাল পোর্ট বা কিউ ব্যবহার করতে হবে সেটি পर्टিকুলার সকেটের জন্য। requestedMaxPacketSize বাফার এলোকেশন টিউন করতে সাহায্য করে যাতে থ্রুপুট এবং পাওয়ার ইফিশিয়েন্সি ব্যালেন্স করা যায়।
এই মুহূর্তে আপনি চিন্তা করতে পারেন, এই ছোট জাভা অবজেক্ট আসলে কীভাবে হার্ডওয়ার পর্যন্ত পৌঁছায়? উত্তর লক্ষ্য হয় HAL (Hardware Abstraction Layer)-এ। যখন আপনি BluetoothSocket.connect() কল করেন, এটিulta নেটিভ কোডের মাধ্যমে ফেলে যেতে থাকে btif_sock.cc এবং btif_core.cc ফাইলগুলোর মতো। সেখানে আপনি এইরকম ট্রেস দেখতে পাবেন:
bt_status_t status = BTA_SockConnect(type, addr, channel, flags); if (settings.data_path == DATA_PATH_HARDWARE_OFFLOAD) { BTIF_TRACE_DEBUG("Configuring socket for hardware offload path"); BTA_SockSetOffloadParams(settings.hub_id, settings.endpoint_id); } এই স্নিপেটটি সরল দেখতে পারে, কিন্তু এটা রেসপন্সিবিলিটির একটি বড় শিফ্ট রিপ্রেজেন্ট করে। প্রতিটি প্যাকেট হোস্ট স্ট্যাকে পাঠানোর বদলে, ব্লুটুথ কন্ট্রোলার এখন ডেটা পাথের ওনারশিপ দাবি করতে পারে। SoC-এর ভেতরের ব্লুটুথ ফার্মওয়ার তারপর দায়িত্ব নেবে, প্যাকেট রিট্রান্সমিশন, একনলেজমেন্ট, এবং ফ্লো কন্ট্রোল হ্যান্ডেল করবে মেইন CPUকে বারবার জাগিয়ে ছাড়া।
আপনি যদি এই কানেকশনের время আপনার ডিভাইসের কার্নেল লগ মনিটর করেন, তবে আপনি এমন কিছু দেখতে পেতে পারেন:
bt_vendor: enabling LPI offload for handle 0x0041 bt_controller: lpi path active, cpu wakelocks released সেই লগ লাইনটি আপনার চুপচাপ নিশ্চিতকরণ যে ডেটা পাথ সফলভাবে লো পাওয়ার আইল্যান্ডে মাইগ্রেট করেছে।
মানুষের ভাষায়, ফোনটি শুধু সিদ্ধান্ত নিয়েছে যে এই ব্লুটুথ কথোপকথনটি যথেষ্ট প্রিডিক্টেবল যাতে মিনি-প্রসেসর হ্যান্ডেল করতে পারে, তাই বড় CPU-কে শিষ্টাচারপূর্ণভাবে বলল, "তুমি এখন একটু ঘুমিয়ে পড়ো। আমি দেখলাম।"
পরবর্তী সেকশনে আমরা এই যাত্রা এক লেয়ার গভীরে ফলো করব, সরাসরি HAL এবং ফার্মওয়ার বাউন্ডারিতে, দেখব কীভাবে এই সকেট সেটিংস আসলে লো-পাওয়ার ডেটা রাউটিং-এ পরিণত হয় কন্ট্রোলার চিপের ভেতরে। ইহায় আসল হার্ডওয়ার ম্যাজিক হয়, এবং বাঁচতো হয় প্রতিটি মিলিয়াট একক সময়।
HAL-এর ভেতর: ব্লুটুথ অফলোড আসলে কীভাবে কাজ করে
এতক্ষণ আমরা অধিকাংশত Android-এর জাভা এবং নেটিভ লেয়ারে আছিলাম, যেখানে ফ্রেমওয়ার্ক এবং সিস্টেম সার্ভিসগুলো বাস করে। কিন্তু তার নিচে থাকে একটি বেসমেন্ট পূর্ণ চতুর মেশিনারি: Hardware Abstraction Layer বা HAL। ইহায় Android "অবজেক্ট"-এ কথা বলা বন্ধ করে "ওপকোড" এবং "বাফার"-এ কথা বলা শুরু করে, এবং সেটা সফটওয়্যার এবং সিলিকনের মধ্যে ব্রিজ।
যখন BluetoothSocketSettings ফ্ল্যাগটি সিস্টেমকে বলে "অনুগ্রহ করে হার্ডওয়ার অফলোড ব্যবহার করুন", সেই রিকোয়েস্টটি জাদুईভাবে চিপে টেলিপোর্ট হয় না। সেটি ধাপে ধাপে ব্লুটুথ স্ট্যাকে নিচে নেমে আসে, JNI (Java Native Interface) পার করে C++-এ, তারপর HAL-এ, যা ডিফাইন করা আছে hardware/interfaces/bluetooth/-এ।
Android 14 থেকে এবং বিশেষ করে AOSP 16-এ, HAL আরও স্মার্ট হয়েছে: এখন এটি LPI ক্যাপাবিলিটি বুঝতে পারে এবং নির্দিষ্ট সকেট ট্রাফিক সেখানে রাউট করতে পারে।
আসুন একটি সরলীকৃত HAL ফাংশনে ঝাঁকি দিই। এটি কাল্পনিক নয়। এটি সেটা দেখতে পেতে পারেন bluetooth_audio_hw.cc বা bluetooth_socket_hal.cc-এ:
Return<void> BluetoothHci::createSocketChannel( const hidl_string& device, const BluetoothSocketSettings& settings, createSocketChannel_cb _hidl_cb) { int fd = -1; if (settings.data_path == DATA_PATH_HARDWARE_OFFLOAD) { ALOGI("LPI offload requested for socket on hub %d endpoint %d", settings.hub_id, settings.endpoint_id); fd = controller->allocateLpiChannel(settings.hub_id, settings.endpoint_id); } else { fd = controller->allocateHostChannel(); } _hidl_cb(Status::SUCCESS, fd); return void(); } সাদা ইংরেজিতে, এই মেথডটি ব্লুটুথ চৌরাস্তার ট্রাফিক অফিসারের মতো। এটি আপনার সকেট সেটিংস দেখে এবং ডিসাইড করে আপনার ডেটা কোন রোডে পাঠাবে। যদি DATA_PATH_HARDWARE_OFFLOAD সেট করা থাকে, ডেটা পাথ কন্ট্রোলারের ইন্টারনাল MCU-তে ওয়ায়ার্ড হয় রেগুলার হোস্ট-সাইড বাফারের বদলে।
controller->allocateLpiChannel() কলটি হলো যেখানে HAL বলে, "ঠিক আছে চিপ, অনুগ্রহ করে তোমার লো-পাওয়ার প্রসেসরের ভেতরেও সম্পূর্ণরূপে বাস করে এমন একটি কিউ তৈরি করো।" এই মাইক্রোকন্ট্রোলার fizikali ব্লুটুথ রেডিওর কাছে থাকে। এটি একনলেজমেন্ট, ছোট ডেটা 버스্ট, এবং এমনকি কিছু প্রোটোকল টাইমিং নিজে হ্যান্ডেল করতে পারে, যেগুলো সাধারণত মেইন CPUকে জাগিয়ে দিত।এই চ্যানেল তৈরি হলে, Android ফ্রেমওয়ার্ক এবং অ্যাপগুলো এখনও একটি নরমাল ফাইল ডেসক্রিপ্টর দেখে, যেন সকেটটি সম্পূর্ণরূপে লোকাল হয়। ম্যাজিকটি রয়েছে এই তথ্যে যে এই ডেসক্রিপ্টর ফার্মওয়ার-ম্যানেজড মেমরি এবং DMA পাথ দ্বারা ব্যাকড রয়েছে Linux কার্নেল বাফার্সের বদলে।
আপনি যদি কন্ট্রোলার থেকে ডিবাগার অ্যাটাচ করুন বা লগ ডাম্প করেন, তবে আপনি এমন কিছু দেখতে পেতে পারেন:
bt_lpi_mcu: channel 0x03 opened for handle 0x0041 bt_hci: diverting ACL packets to LPI path bt_lpi_mcu: sleeping host processor সেই তৃতীয় লাইন, sleeping host processor, পাওয়ার ইঞ্জিনিয়ারদের স্বপ্ন সত্যি। ফোন শाब্দিকভাবে CPU সাবসিস্টেমের বড় অংশ বন্ধ করে দিচ্ছে ব্লুটুথ জীবন্ত রাখতে।
এটাও যেখানে ভেন্ডররা যেন Qualcomm বা Broadcom তাদের স্পেশাল সস যোগ করে। তাদের HAL-এ প্রায়শই এক্সট্রা হুক থাকে "keep-alive" টাইমার, "কোয়েলেসিং ইন্টারভাল", এবং "ফার্মওয়ার-ড্রাইভেন রিট্রান্সমিশন"-এর জন্য। এগুলো নিশ্চিত করে কানেকশন اسمুথ লাগে এমনকি মেইন প্রসেসর অফ-ডিউটি থাকলে।
হাই-লেভেল ভিউ থেকে, পাইপলাইন এখন এরকম দেখে:
App -> Bluetooth Framework -> JNI -> btif_sock -> HAL -> Controller MCU (LPI) প্রতিটি লেয়ার পর্যাপ্ত বুঝতে পারে পরেরটিকে ক্লিনলি ব্যাটন পাস করার জন্য। HAL অহঁকারি ট্রান্সলেটর হিসেবে কাজ করে, হাই-লেভেল সেটিংস নেয় এবং সেগুলো লো-লেভেল কমান্ডে রূপান্তর করে যা চিপ ফার্মওয়ার এক্সিকিউট করতে পারে।
আপনার স্মার্টওয়াচ প্যাকেট পাঠালে বা আপনার ইয়ারবাডস অডিও চান্ক রিকোয়েস্ট করলে, মেইন CPU একবারে পলক ঝাপকেও দেয় না। সম্পূর্ণ ট্রানজেকশন ব্লুটুথ কন্ট্রোলারের ছোট ডোমেনে বাস করে ও মরে, পাওয়ার সিপ করে না গল্প করে।
পরবর্তী সেকশনে, আমরা এক্সপ্লোর করব কীভাবে এই অফলোড আর্কিটেকচার Android-এর পাওয়ার ম্যানেজমেন্ট সিস্টেমের সাথে ইন্টিগ্রেট হয়, যার মধ্যে রয়েছে ওয়েকলক, ডোজ মোড, এবং কার্নেল কোঅর্ডিনেশন, এবং কীভাবে এটি নিশ্চিত করে যে মেইন CPU ঘুমালেও কানেকশন কখনো বিট মিস করে না।
CPU ঘুমিয়ে থাকলে কিন্তু ব্লুটুথ জেগে থাকে: পাওয়ার ম্যানেজমেন্ট একশনে
ঠিক আছে, আমরা দেখেছি কীভাবে সকেট অফলোড অ্যাপ লেয়ার থেকে HAL-এ এবং অবশেষে সেই ছোট MCU-তে ল্যান্ড করে যা ব্লুটুথ চিপের ভেতরে বাস করে। কিন্তু এরপর কী হয়? আপনার ফোনের মেইন CPU যদি একটু ঘুমাতে চায় এক ফাইল ট্রান্সফার বা অডিও স্ট্রিম চলাকালীন? এটা কি ব্লুটুথ কানেকশন ভাঙার রিস্ক নেই?
ইহায় Android-এর পাওয়ার ম্যানেজমেন্ট কোরিওগ্রাফি এসে পড়ে। এটি তিনটি পারফরমারের মধ্যে একটি নৃত্য: Power HAL, Bluetooth stack, এবং কার্নেল ওয়েকলক সিস্টেম।
যখন একটি ব্লুটুথ সকেট Low Power Island-এর জন্য কনফিগার করা হয়, Android-এর ব্লুটুথ স্ট্যাক কার্নেলকে সিগন্যাল দেয় যে এই কানেকশন মেইন CPU-এর সাহায্য ছাড়া মেইনটেইন করা যাবে। ইন্টারন্যালি, এটি ওয়েকলক টাইমার ক্লিয়ার বা ডাউনস্কেল করে যা সাধারণত ব্লুটুথ ট্রাফিকের время প্রসেসরকে জাগিয়ে রাখে। কার্নেল লগে আপনি এমন কিছু দেখতে পেতে পারেন:
wakelock: release "bt_wake" (LPI mode active) bt_controller: firmware handling link supervision locally এই মেসেজ সিস্টেম ইঞ্জিনিয়ারদের জন্য সোনা। এটি বলে দেয় কন্ট্রোলার কানেকশনের ফুল ওনারশিপ নেয়েছে। ব্লুটুথ ফার্মওয়ার এখন সুপারভিশন টাইমআউট মনিটর করছে, রিট্রান্সমিশন হ্যান্ডেল করছে, এবং এনক্রিপশন কাউন্টার মেইনটেইন করছে।
পাওয়ার ম্যানেজারের দৃষ্টিতে, ব্লুটুথ ডিভাইসটি "আইডেল" দেখে কারণ মেইন CPU-তে কোনো ইন্টারাপ্ট জেনারেট হচ্ছে না। একই সাথে, কন্ট্রোলার MCU শান্তভাবে আপনার ইয়ারবাডস বা স্মার্টওয়াচের সাথে প্যাকেট এক্সচেঞ্জ করছে তার নিজস্ব লো-পাওয়ার ক্লক ডোমেন ব্যবহার করে।
এটি কোঅর্ডিনেট করতে, ব্লুটুথ HAL ছোট কলব্যাক এক্সপোজ করে যা পাওয়ার HAL-কে জানায় যতক্ষণ ট্রাফিক লেভেল পরিবর্তন হয়। আপনি bt_vendor_qcom.cc-এ এমন কিছু স্নিপেট পেতে পারেন:
void bt_lpi_activity_update(bool active) { if (active) power_hint(POWER_HINT_LPI_ACTIVITY, 1); else power_hint(POWER_HINT_LPI_ACTIVITY, 0); } যখন active শূন্যে যায়, পাওয়ার HAL জানে এটি ডিপার সিস্টেম স্লিপ স্টেটস (যেমন suspend-to-RAM) অনুমতি দিতে পারে, কারণ ব্লুটুথ নিজে সঠিক রাখবে।
রিয়াল ম্যাজিকটি হলো ইউজার কখনো এই কোনোটা লক্ষ্য করে না। ফোন "ঘুমিয়ে থাকা" লাগতে পারে, ডিসপ্লে অফ, CPU কোর গেটেড, কিন্তু আপনার ব্লুটুথ অডিও এখনও বাজছে, আপনার স্মার্টওয়াচ এখনও সিঙ্ক হচ্ছে, এবং আপনার ফোন আবিষ্কারযোগ্য থাকছে।
এটা প্রায় কাব্য। মেইন প্রসেসর স্বপ্ন দেখছে, কন্ট্রোলার মৃদু গুনগুনাচ্ছে, এবং আপনার প্লেলিস্ট চলতে থাকছে যেন কিছুই হয়নি।
আপনি যদি একটি রিয়াল Android ডিভাইসে এটি ভেরিফাই করতে চান, তবে আপনি এই কমান্ড ব্যবহার করতে পারেন:
adb shell cat /sys/kernel/debug/wakeup_sources | grep bt যখন আপনি দেখবেন bt_wake কাউন্টার স্ট്രീমিং-এর সময়ও কম থাকে, অভিনন্দন! লো পাওয়ার আইল্যান্ড অফলোড খুব সুন্দরভাবে কাজ করছে।
পরবর্তী সেকশনে, আমরা ফার্মওয়ার গভীর থেকে উঠে আসব দেখতে এই সব রোজমর্রা ডেভেলপারদের ওয়ার্ল্ডে কীভাবে ফিট হয়। আপনি, একজন অ্যাপ বা সিস্টেম ডেভেলপার হিসেবে, কি আসলে এই সকেট সেটিংস সরাসরি কন্ট্রোল বা বেনিফিট করতে পারেন? এবং এগুলো বুঝতে কীভাবে আপনাকে সাহায্য করতে পারে ব্লুটুথ অ্যাপ বানাতে যা পাওয়ার সিপ করে না গল্প করে?
ডেভেলপাররা কীভাবে BluetoothSocketSettings ব্যবহার করতে পারে
এখন যেন ব্লুটুথ স্ট্যাকে হৃদয়ের গভীরে ঝাঁকি দিয়ে, আসুন ওই লেয়ারে ফিরে যাই যেখানে আপনি এবং আমি বাস করি: ডেভেলপার লেয়ার। আপনি ভাবতে পারেন, "ঠিক আছে, সকল হার্ডওয়ার উইজার্ডরি চমৎকার, কিন্তু আমি আসলে কী করতে পারি এটা দিয়ে?"
মজার অংশটি হলো: যদিও Low Power Island অধিকাংশ একটি সিস্টেম-লেভেল ফিচার, এটি কীভাবে কাজ করে সেটা বুঝলে আপনি ব্লুটুথ অ্যাপ ডিজাইন করতে পারেন যা আরও পাওয়ার-ফ্রেন্ডলি এবং প্রিডিক্টেবল।
ফ্রেমওয়ার্ক লেভেলে, আপনি সরাসরি LPI অন বা অফ টগল করতে পারবেন না আপনার অ্যাপ থেকে। সেই সইচগুলো গভীরে থাকে সিস্টেম কম্পোনেন্টগুলোর মতো BluetoothService এবং BluetoothSocketManagerService-এ। কিন্তু প্রতিবার আপনি একটি BluetoothSocket বা BluetoothServerSocket ব্যবহার করেন, আপনার ডেটা স্লেন্টলি সেই লেয়ারগুলোতে ফ্লো করে যা চেক করে LPI অফলোড উপলব্ধ কিনা।
একমানে আপনার অ্যাপটি অটোমেটিক্যালি বেনিফিট পায়, যতক্ষণ আপনি এমন কিছু করবেন না যা CPUকে অনাবশ্যকভাবে জাগিয়ে রাখে। উদাহরণস্বরূপ, প্রপার থ্রেড স্লিপ ব্যবহার করা, বুজি লুপ এড়ানো, এবং Android-এর নিজস্ব ব্লুটুথ I/O স্ট্রিমগুলো বাফারিং হ্যান্ডেল করতে দেয়া আপনাকে অফলোড লজিকের কৃপায় রাখবে।
আপনি যদি AOSP-এর সিস্টেম সার্ভার লগে ডুবান থাকেন ব্লুটুথ সকেট কানেক্ট করার সময়, তবে আপনি এমন কিছু লক্ষ্য করতে পারেন:
BluetoothSocketManager: Offload eligible socket detected, enabling LPI mode Bluetooth HAL: LPI channel activated for fd=42 সেই ছোট লাইনটি বলে দেয় যে আপনার সকেট চুপচাপ আইল্যান্ডের মাধ্যমে রি-রাউট করা হয়েছে, আপনি একটা আঙ্গুল না হিলিয়ে।
আন্ডারneath, ফ্রেমওয়ার্ক একটি BluetoothSocketSettings অবজেক্ট তৈরি করেছিল এবং সেটি চেইন নিচে পাস করেছিল যখন সকেটটি খোলা হয়েছিল। সূডো-জাভাতে, এটি এরকম দেখে:
BluetoothSocketSettings settings = new BluetoothSocketSettings( BluetoothSocketSettings.DATA_PATH_HARDWARE_OFFLOAD, /* hubId */ 1, /* endpointId */ 2, /* maxPacketSize */ 512); BluetoothSocket socket = adapter.createSocket(device, settings); socket.connect(); নিশ্চিতভাবেই, এটি এখনও পাবলিক SDK-তে নয়, কিন্তু সিস্টেম অ্যাপ বা প্রিভিলেজড ফ্রেমওয়ার্ক সিমিলার কলস ব্যবহার করে ট্রাফিক কীভাবে হ্যান্ডেল হবে সেটা বর্ণনা করতে।
তাহলে আপনি, ডেভেলপার হিসেবে, কেন যত্ন দিবেন? কারণ জানা যে এই পাথটি অস্তিত্ব রেখেছে মানে আপনি এটি ধরে রেখে ডিজাইন করতে পারেন। উদাহরণস্বরূপ, আপনি পারেন:
ছোট BLE রাইটস ব্যাচ করা একটা একটা পাঠানোর বদলে, যাতে কন্ট্রোলার সেগুলো অফলোড বাফারের ভেতরে কার্যকরভাবে প্রসেস করতে পারে।
বাড়াবার কানেক্ট/ডিসকানেক্ট সাইকেল এড়ানো, যা স্ট্যাককে বাধ্য করবে মেইন CPUকে বারবার জাগিয়ে তোলার জন্য।
আপনার ব্যাকগ্রাউন্ড ট্রান্সফার স্ট্রাকচার করা যাতে সেগুলো লো-পাওয়ার বাফার্সের লিমিটের ভেতরে ফিট করে (ছোট চাঙ্ক এবং লম্বা ইন্টারভাল ভাবুন)।
মৌলিকভাবে, আপনার ডেটা প্যাটার্ন যত বেশি প্রিডিক্টেবল, তত বেশি সম্ভাবনা সেটি হোস্টকে জাগিয়ে ছাড়া আইল্যান্ডে থাকবে।
আপনি যদি সিস্টেম সফটওয়্যার বানান, বলুন একটি কাস্টম Android ডিভাইস বা এম্বেডেড প্রোডাক্টের জন্য, তবে আপনি আরও آگেও যেতে পারেন। আপনি HAL বিয়হেভিয়র টিউন করতে পারেন, কাস্টম hub বা endpoint ID অ্যাসাইন করতে পারেন, এবং এমনকি मैক্সিমাম প্যাকেট সাইজ টিউন করতে পারেন যা ফার্মওয়ার DMA ট্রান্সফারের জন্য ব্যবহার করে। এটি আপনাকে ব্লুটুথ ফিচার বানাতে দেয়: যেন লো-এনার্জি টেলিমেট্রি স্ট্রিমিং বা ওয়িয়ারেবল সেন্সর সিঙ্ক, যা প্রায় সম্পূর্ণরূপে অফলোডেড চলে।
সেই মুহূর্তে, আপনার ব্লুটুথ চিপ একটি মিনি সার্ভারে রূপান্তর হয় যা মেইন OS ঘুমালেও কাজ করে চলছে, বাতারি লাইফ এবং স্ন্যাপি রিকানেকশন দিয়ে।
শেষ সেকশনে, আমরা সব কিছু র্যাপ আপ করব এবং বড় ছবিতে ফিরে দেখব, কেন BluetoothSocketSettings এবং Low Power Island মিলিতভাবে Android-এর "ইনভিজিবল ইঞ্জিনিয়ারিং"-র সবচেয়ে এলিগ্যান্ট উদাহরণের একটি রিপ্রেজেন্ট করে। এটি এমন একটি চুপচাপ জয় যা আপনি কখনো কিনোতে দেখবেন না কিন্তু প্রতিদিন অনুভব করবেন যখন আপনার ফোন মিডনাইটে এখনও জুসदार থাকে।
শেষ অধ্যায়: স্মার্টলি ঘুমানোর এলেগ্যান্স
একটা মিনিট ফিরে যাই। আমরা শুরু করেছি একটি কফি শপে একটা ওভারওয়ার্কড বারিস্টার দিয়ে। তারপর আমরা একটি লুকানো অ্যাসিস্টেন্ট আবিষ্কার করেছি, লো পাওয়ার আইল্যান্ড, যা চুপচাপ ক্যাফেটিয়া চালিয়ে যাচ্ছে এমনকি মেইন বারিস্টার ছুটি নিলেও।
আমরা একটি বিনীত ব্লুটুথ সকেটের পাথ ফলো করেছি, দেখেছি এটা BluetoothSocketSettings-এ র্যাপ হয়ে, HAL-এ যাত্রা করেছি, এবং অবশেষে একটি মিনিয়েচার প্রসেসরে ল্যান্ড করেছি কন্ট্রোলারের ভেতরে যা হাম করছে বড় CPU স্বপ্ন দেখার সময়।
এটাই সৌন্দর্য: Android-এর ব্লুটুথ অফলোড মেকানিজম ইনভিজিবল ইঞ্জিনিয়ারিং-এর সবচেয়ে এলিগ্যান্ট উদাহরণের একটি। এটি কোনো নতুন API বা ফ্যান্সি অ্যানিমেশন দিয়ে ঘোষণা করছে না। এটি শুধু চুপচাপ আপনার ব্যাটারি বেশি দিন টিকিয়ে রাখে, আপনার ব্লুটুথ আরও নির্ভরযোগ্য করে, এবং আপনার ফোন স্মুথ লাগে, আপনি জানতেও পারেন না যে সেটা সেখানে আছে।
টেকনিক্যাল পয়েন্ট অফ ভিউতে, ব্রিলিয়েন্সটি রয়েছে ব্যালেন্সে। সিস্টেম এখনও ফুল-ফিচার্ড সকেট এবং রিচ প্রোটোকল হ্যান্ডেলিং অনুমতি দেয় যখন আপনাকে দরকার, কিন্তু কমন ডেটা ফ্লোর জন্য, অডিও, টেলিমেট্রি, নোটিফিকেশন, বা হার্ট রেট স্ট্রিমিং, এটা লো-পাওয়ার কন্ট্রোলারকে স্টিয়ারিং হুইল দিয়ে দেয়। এটি যেন Android ডেলিগেশন শিখেছে।
প্রতিবার আপনার স্মার্টওয়াচ সিঙ্ক হয় যখন আপনার ফোন স্ক্রিন অফ, বা আপনার ইয়ারবাডস লম্বা ফ্লাইটে কানেক্টেড থাকে ব্যাটারি ড্রেইন ছাড়া, আপনি BluetoothSocketSettings এবং লো পাওয়ার আইল্যান্ড ফ্রেমওয়ার্ককে কাজ করছেন দেখছেন। এগুলো মডার্ন Android ডিজাইন ফিলোসফির একটি বড় অংশ, বুদ্ধিমত্তা হার্ডওয়ারের কাছে নিয়ে যাওয়া। আমরা আমাদের চিপগুলোকে যত বেশি অটোনোমাস টাস্ক হ্যান্ডেল করতে শিখাব, তত বেশি আমরা মেইন প্রসেসরকে বিশ্রাম দিতে পারব।
আপনি যদি একজন ডেভেলপার বা সিস্টেম ইঞ্জিনিয়ার হন, এই আর্কিটেকচার বুঝতে শুধু একাডেমিক নয়। এটি আপনার নিজস্ব ফিচার ডিজাইন করতে ইনস্পায়ার করতে পারে। আপনি কাস্টম Android ROM বানান, ওয়িয়ারেবলস জন্য ফার্মওয়ার অপ্টিমাইজ করেন, বা ব্লুটুথ চিপসহ IoT ডিভাইস তৈরি করেন, পাঠ্যটি স্পষ্ট: আপনার মেইন CPUকে প্রতিটি প্যাকেটের বেবিসিটিং করাবেন না। অফলোড করুন যখন পারেন, ঘুমিয়ে যান যখন উচিত, এবং আপনার ডিভাইসগুলো আপনাকে ধন্যবাদ জানাবে এক্সট্রা আপটাইমের ঘন্টার সাথে।
তাই পরবারের কোনো সময় আপনি আপনার ইয়ারবাডস প্লাগ ইন করবেন এবং লক্ষ্য করবেন আপনার ফোন কুল থাকছে এবং আপনার ব্যাটারি পার্সেন্টেজ কিনचित হিলছে না, মনে রাখবেন: কোথাও গভীরে, একটি ছোট ব্লুটুথ MCU সকল ভারী কাজ করছে যখন মেইন CPU তার লো-পাওয়ার হ্যামকে ঘুমাচ্ছে।
এটাই Android-এর লো পাওয়ার আইল্যান্ড এবং BluetoothSocketSettings-এর চুপচাপ জিনিয়াসিটি। এটা শুধু ব্লুটুথ সম্পর্কে নয়। এটা আমাদের ডিভাইসগুলোকে বিজি নয়, স্মার্টার হওয়া শিখাতে। এবং হয়তো, শুধু হয়তো, সেটা একটি পাঠ যা আমরা নিজেদের জন্যও মনে রাখতে পারি।
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started